diff --git a/.docker/api/Dockerfile b/.docker/api/Dockerfile index 92e0355b4..f907baaf0 100644 --- a/.docker/api/Dockerfile +++ b/.docker/api/Dockerfile @@ -1,4 +1,4 @@ -FROM node:8.9.0 +FROM node:8.11.1 WORKDIR /usr/src/app diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index ec851d82b..3ecaab7e2 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,31 +1,30 @@ # How to Contribute? ## Project members - - Create an issue - Create a branch for that issue with the naming: `feature/{ticket-no}-{description-separated-by-dashes}` - Develop your code - Commit and push in regular intervalls - Run the tests locally +- Add a line to the [CHANGELOG.md](https://github.com/h-da/geli/blob/develop/CHANGELOG.md) under the "NEXT" section in the form `- a short text to describe [#123](https://github.com/h-da/geli/issues/123)` - Open a Pull-Request - If CI/Coverage give their OK we can merge - The PR gets merged to `develop`, which will push a new Docker-Image-Version with the tag `develop` and `latest` - The staging-system will then be updated to the latest Image from Docker-Hub - If we have enough features we will merge the `develop` into the `master` branch, which will add - a new 'stable' image on Docker-Hub. + a new 'stable' image on Docker-Hub. Before we do this, the new version needs to be updated in several `package.json`s and the `CHANGELOG.md`. The livesysten then pulls that new image and starts up with the latest stable version -If we have bugfixes we create a `bugfix/{descriptive-name}` and open a PR, issues are not required +If we have small bugfixes we create a `bugfix/{descriptive-name}` and open a PR, issues are not required for that. But it's important to have a good description of the bugfix in the PR-Comment. +If it is not a small bug please create a issue for it so we can decide the importance of it. ## Branching model - We are using a slightly modified [GitFlow](https://datasift.github.io/gitflow/IntroducingGitFlow.html) branching strategy. ## Commit messages - Please adhere to the principles described [here](https://chris.beams.io/posts/git-commit/) for writing commit messages. diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index b19026114..8ae8ca007 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -14,5 +14,7 @@ ## Additional info: ------- -_Please tag this issue if you are sure to which tag(s) it belongs._ + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index f63a83f51..67c90965a 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -9,6 +9,8 @@ Closes # ## Known Issues: _NONE_ ------- -_Remember to prefix your PR-Title with `⚠ WIP: ` if you still work on it. -If you have reached a final state, remove the prefix._ + diff --git a/.travis.yml b/.travis.yml index d88fe3aa3..ff4b3cc9d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -62,6 +62,8 @@ install: - cd .. script: + # check for change in changelog + - .travis/changelog.sh # check for versions - .travis/check-version.sh # run license checker and write license.json / dependencies.ts @@ -74,11 +76,11 @@ script: # run frontend-tests and return back to root for following steps - cd app/webFrontend - npm run lint # run linter - # - npm run test # run test - does not work properly + # - npm run test-ci || true # run test - many tests are broken - npm run e2e # run end-to-end-tests - sed -i 's/$TRAVIS_COMMIT/'$TRAVIS_COMMIT'/' src/app/shared/services/raven-error-handler.service.ts - cd ../.. - - .travis/build-fe.sh # build in prod mode + - travis_wait 30 .travis/build-fe.sh # build in prod mode after_script: # send required files to coveralls.io diff --git a/.travis/apidoc.sh b/.travis/apidoc.sh index 42f8253ae..b34428a99 100755 --- a/.travis/apidoc.sh +++ b/.travis/apidoc.sh @@ -45,7 +45,7 @@ if [[ "$TRAVIS_BRANCH" == "master" ]] || [[ -n "$TRAVIS_TAG" ]]; then git commit -m "Travis build: $TRAVIS_BUILD_NUMBER" &>/dev/null if [[ -n "$TRAVIS_TAG" ]]; then - echo "+ git tag" ; git tag $TRAVIS_TAG + echo "+ git tag" ; git tag -a $TRAVIS_TAG -m "Release $TRAVIS_TAG" else echo -e "${YELLOW}+ skipping: git tag - not tagged build${NC}" fi diff --git a/.travis/changelog.sh b/.travis/changelog.sh new file mode 100755 index 000000000..cfc1836d8 --- /dev/null +++ b/.travis/changelog.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +# Path to this file +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +# Path the script was called from +IPWD="$(pwd)" +# Import shared vars +. ${DIR}/_shared-vars.sh + +echo +echo "+++ Check if changelog was updated +++" +echo + + +if [ "$TRAVIS_PULL_REQUEST" != "false" ] && [ "$TRAVIS_BRANCH" == "develop" ]; then + echo "+ detected pull request from ($TRAVIS_PULL_REQUEST_BRANCH) to $TRAVIS_BRANCH" + curl --silent https://raw.githubusercontent.com/h-da/geli/$TRAVIS_BRANCH/CHANGELOG.md \ + | diff CHANGELOG.md - \ + | grep -P '^< - .{8,}' - -q + + if [[ $? == 0 ]]; then + echo -e "${GREEN}+ Update in CHANGELOG.md found, exit${NC}" + else + echo -e "${RED}+ ERROR: No Update in CHANGELOG.md found!" + echo -e "+ Please check if a line was added in the CHANGELOG.md.${NC}" + exit 1 + fi +elif [ "$TRAVIS_PULL_REQUEST" != "false" ] && [ "$TRAVIS_BRANCH" == "master" ]; then + echo "+ detected pull request from ($TRAVIS_PULL_REQUEST_BRANCH) to $TRAVIS_BRANCH" + curl --silent https://raw.githubusercontent.com/h-da/geli/$TRAVIS_BRANCH/CHANGELOG.md \ + | diff CHANGELOG.md - \ + | grep -P '^< ## \[\[\d{1,3}\.\d{1,3}\.\d{1,3}\].*\] - \d{4}-\d{2}-\d{2} - .{10,}' - -q + + if [[ $? == 0 ]]; then + echo -e "${GREEN}+ Update in CHANGELOG.md found, exit${NC}" + else + echo -e "${RED}+ ERROR: No Update in CHANGELOG.md found!" + echo -e "+ Please check if a new version was added in the CHANGELOG.md." + echo -e "+ Or a new section for the next release was added${NC}" + exit 1 + fi +else + echo -e "${YELLOW}+ WARNING: No Pull Request agiainst Develop or Master -> skipping automate changelog checking${NC}"; +fi diff --git a/.travis/check-version.sh b/.travis/check-version.sh index 1f54f956e..3f151dcb5 100755 --- a/.travis/check-version.sh +++ b/.travis/check-version.sh @@ -10,7 +10,7 @@ IPWD="$(pwd)" PATHS_TO_CHECK=("api" "app/webFrontend") echo -echo "+++ Check if current version already used" +echo "+++ Check if current version already used +++" echo # If is PR against master diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..66471bf03 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,133 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). + + + +## [NEXT] + +## [[0.7.0](https://github.com/h-da/geli/releases/tag/v0.7.0)] - 2018-05-05 - SS 18 intermediate Release +### Added +- Added the possibility to sort all courses alphabetically. [#567](https://github.com/h-da/geli/issues/567) +- Added a box for information on the homescreen. [#216](https://github.com/h-da/geli/issues/216) +- Added an account activation resend feature. [#601](https://github.com/h-da/geli/issues/601) +- Added `SnackBarService` as wrapper for `MatSnackBar`. [#574](https://github.com/h-da/geli/issues/574) +- Added new course & user API unit tests. [#654](https://github.com/h-da/geli/issues/654) [#691](https://github.com/h-da/geli/issues/691) +- Added details of courseAdmin and teacher to course detail view. on click profiles are shown.[#598](https://github.com/h-da/geli/issues/598) +- Added small auto linting scripts to package.json [#688](https://github.com/h-da/geli/issues/688) +- Added changed size of drop down arrows for better usability. [#686](https://github.com/h-da/geli/issues/686) +- Added new contributors [#624](https://github.com/h-da/geli/issues/624) +- Added the date and the teacher under each unit [#582](https://github.com/h-da/geli/issues/582) +- Added E-Mail validation to reset password [#597](https://github.com/h-da/geli/issues/597) +- Added Language code to header [#554](https://github.com/h-da/geli/issues/554) +- Added icon for access key [#547](https://github.com/h-da/geli/issues/574) +- Unit visibility toggle [#582](https://github.com/h-da/geli/issues/582) + +### Changed +- Refactored or slightly altered various course & user related APIs. [#654](https://github.com/h-da/geli/issues/654) [#691](https://github.com/h-da/geli/issues/691) +- Removed firstname from resend activation feature and change button positioning. [#711](https://github.com/h-da/geli/issues/711) +- Refactored register and resend activation to use geli email validator with top level domain check. [#713](https://github.com/h-da/geli/issues/713) +- Refactored the unitCreator with a forsafe user object. [#717](https://github.com/h-da/geli/pull/717) +- Changed the text in download course[#718](https://github.com/h-da/geli/pull/718) +- Removed firstname from resend activation feature and change button positioning. [#711](https://github.com/h-da/geli/issues/711) +- Refactored register and resend activation to use geli email validator with top level domain check. [#713](https://github.com/h-da/geli/issues/713) + +### Fixed +- Fixed route `/users/roles` [#204](https://github.com/h-da/geli/issues/204) +- Fixed profile picture will be deleted after changing any other profile data [#504](https://github.com/h-da/geli/issues/504) +- Fixed some UI issues in create code kata unit [#543](https://github.com/h-da/geli/issues/543) +- Fixed reading wrong error message across the whole application [#572](https://github.com/h-da/geli/issues/572) +- Fixed admin can changed his own role [#606](https://github.com/h-da/geli/issues/606) +- Fixed a typo in admin panel [#533](https://github.com/h-da/geli/issues/533) +- Fixed an admin cannot delete any courses [#647](https://github.com/h-da/geli/issues/647) +- Fixed some issues with download a course [#659](https://github.com/h-da/geli/issues/659) +- Fixed an issue with deleting a course and the notification was not triggered [#642](https://github.com/h-da/geli/issues/543) +- Fixed Course progress mechanism [#593](https://github.com/h-da/geli/issues/593) +- Fixed wasteful course data usage via specialized course model interfaces. [#654](https://github.com/h-da/geli/issues/654) +- Fixed a broken documentation link. [#583](https://github.com/h-da/geli/issues/583) +- Limited the first and last name to 64 characters in the registration- and edit page. [#585](https://github.com/h-da/geli/issues/585) +- Added a correct email validator to the `user-edit` and `register` components. [#564](https://github.com/h-da/geli/issues/564) +- Upload of profile pictures now prevents files with forbidden extensions. [#581](https://github.com/h-da/geli/issues/581) +- Fixed empty course downloads. [#659](https://github.com/h-da/geli/issues/659) +- Videos in the course now get sized equally and can't grow too big in mobile views. [#534](https://github.com/h-da/geli/issues/534) +- Fixed missing background on the password reset page. [#673](https://github.com/h-da/geli/issues/673) +- Fixed notification icon spacing in the navbar for students. [#696](https://github.com/h-da/geli/issues/696) +- Repair Angular CLI code generation. [#701](https://github.com/h-da/geli/pull/701) +- Fixed `tsconfig.spec.ts` for `ng test`. [#656](https://github.com/h-da/geli/pull/656) +- Fixed `.travis.yml`. [#706](https://github.com/h-da/geli/pull/706) +- Fixed wording of progress display on profile page. [#715](https://github.com/h-da/geli/issues/715) +- Fixed form validator in create task [#579](https://github.com/h-da/geli/issues/579) +- Fixed Mongoose pre hook usage [#680](https://github.com/h-da/geli/issues/680) [#677](https://github.com/h-da/geli/issues/677) + +### Security +- Fixed numerous severe user related security issues. [#691](https://github.com/h-da/geli/issues/691) [#709](https://github.com/h-da/geli/pull/709) +- Fixed multiple severe course related security issues. [#594](https://github.com/h-da/geli/issues/594) [#653](https://github.com/h-da/geli/issues/653) [#691](https://github.com/h-da/geli/issues/691) +- Updated the dependencies for security. [#661](https://github.com/h-da/geli/issues/661) + +## [[0.6.0](https://github.com/h-da/geli/releases/tag/v0.6.0)] - 2018-03-31 - Introduces MediaManager and some minor changes +### Added +- MediaManager for file management in courses + + +## [[0.5.0](https://github.com/h-da/geli/releases/tag/v0.5.0)] - 2018-03-24 - WS 17/18 intermediate Release +### Added +- selective download of the course +- progress dashboard for teacher +- translateable frontend with i18n +- notification system added +- introduces new error message system +- dark theme option +- introducing an api documentation +- courses are ordered by last visit +- user password edit +- adds imprint + + +## [[0.4.0](https://github.com/h-da/geli/releases/tag/v0.4.0)] - 2017-12-04 - WS 17/18 Second feature release +### Added +- Responsivness improved +- leave course function +- delete course +- import/export course function +- free text mail to students +- dragging content between lectures +- consistent save and abort btns in units +- progress component +- duplication of lectures +- randomize tasks after validation + + +## [[0.3.1](https://github.com/h-da/geli/releases/tag/v0.3.1)] - 2017-11-05 - Dynamic db name update +### Added +- The possibility to use a other database name then 'test' + + +## [[0.3.0](https://github.com/h-da/geli/releases/tag/v0.3.0)] - 2017-11-02 +### Added +- a lot of major bugfixes and optimizations + + +## [[0.2.2](https://github.com/h-da/geli/releases/tag/v0.2.2)] - 2017-10-19 - Security improvements +### Added +- security for free courses + + +## [[0.2.1](https://github.com/h-da/geli/releases/tag/v0.2.1)] - 2017-10-03 - First Live-Ready release +### Added +- first live functionality + + +## [[0.2.0](https://github.com/h-da/geli/releases/tag/v0.2.0)] - 2017-06-29 - Almost production ready +### Added +- Many new feature for production + + +## [[0.1.0](https://github.com/h-da/geli/releases/tag/v0.1.0)] - 2017-05-11 - Basics implemented +### Added +- Many basic implementations of ground functionality diff --git a/api/fixtures/FixtureLoader.ts b/api/fixtures/FixtureLoader.ts index 10e620695..95fef6498 100644 --- a/api/fixtures/FixtureLoader.ts +++ b/api/fixtures/FixtureLoader.ts @@ -23,7 +23,7 @@ export class FixtureLoader { (mongoose).Promise = global.Promise; if (!mongoose.connection.readyState) { - mongoose.connect(config.database, {useMongoClient: true}); + mongoose.connect(config.database); } } @@ -78,7 +78,7 @@ export class FixtureLoader { for (const file of files) { if (!fs.existsSync(file.path) && fs.existsSync(this.binaryDirectory + file.alias)) { - fs.copyFileSync(this.binaryDirectory + file.alias, file.path) + fs.copyFileSync(this.binaryDirectory + file.alias, file.path); } } })); diff --git a/api/fixtures/FixtureUtils.ts b/api/fixtures/FixtureUtils.ts index f1d14f072..743d5ac88 100644 --- a/api/fixtures/FixtureUtils.ts +++ b/api/fixtures/FixtureUtils.ts @@ -56,6 +56,17 @@ export class FixtureUtils { return this.getRandom(array, hash); } + public static async getRandomActiveStudent(hash?: string): Promise { + const array = await User.find({role: 'student', isActive: true}); + return this.getRandom(array, hash); + } + + + public static async getRandomInactiveStudent(hash?: string): Promise { + const array = await User.find({role: 'student', isActive: false}); + return this.getRandom(array, hash); + } + public static async getRandomStudents(min: number, max: number, hash?: string): Promise { const array = await this.getStudents(); return this.getRandomArray(array, min, max, hash); @@ -71,7 +82,7 @@ export class FixtureUtils { lastName: stud.profile.lastName, uid: stud.uid, courseId: new ObjectId(course._id) - } + }; }); } @@ -175,7 +186,7 @@ export class FixtureUtils { const shuffeledArray = this.shuffleArray(array); const count = this.getRandomNumber(min, max); const start = this.getRandomNumber(0, shuffeledArray.length - count); - return shuffeledArray.slice(start, start + count) + return shuffeledArray.slice(start, start + count); } } diff --git a/api/fixtures/courses/Access-key-test.json b/api/fixtures/courses/Access-key-test.json new file mode 100644 index 000000000..e7cdf5c90 --- /dev/null +++ b/api/fixtures/courses/Access-key-test.json @@ -0,0 +1,23 @@ +{ + "name": "Access key test", + "description": "This course is used to test the access key course enroll type.", + "active": true, + "whitelist": [], + "enrollType": "accesskey", + "accessKey": "accessKey1234", + "hasAccessKey": true, + "lectures": [ + { + "name": "Documentation", + "description": "Documents the course fixture.", + "units": [ + { + "name": "What is the purpose of this course fixture?", + "description": "", + "markdown": "To test the 'accesskey' enrollType.", + "__t": "free-text" + } + ] + } + ] +} diff --git a/api/fixtures/users/studentFixtures.json b/api/fixtures/users/studentFixtures.json index 8f6123a96..6914cb336 100644 --- a/api/fixtures/users/studentFixtures.json +++ b/api/fixtures/users/studentFixtures.json @@ -328,5 +328,27 @@ "lastName": "Mollenhauer" }, "isActive": true + }, + { + "uid": "987654", + "email": "student31@test.local", + "password": "test1234", + "role": "student", + "profile": { + "firstName": "Robert", + "lastName": "Kapinski" + }, + "isActive": false + }, + { + "uid": "987653", + "email": "student32@test.local", + "password": "test1234", + "role": "student", + "profile": { + "firstName": "Horst", + "lastName": "Mengalo" + }, + "isActive": false } ] diff --git a/api/package-lock.json b/api/package-lock.json index fd26300cb..396334753 100644 --- a/api/package-lock.json +++ b/api/package-lock.json @@ -10,25 +10,11 @@ "integrity": "sha1-z6I7xYQPkQTOMqZedNt+epdLvuE=", "dev": true, "requires": { - "acorn": "5.2.1", + "acorn": "5.5.3", "css": "2.2.1", "normalize-path": "2.1.1", "source-map": "0.5.7", "through2": "2.0.3" - }, - "dependencies": { - "acorn": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.2.1.tgz", - "integrity": "sha512-jG0u7c4Ly+3QkkW18V+NRDN+4bWHdln30NL1ZL2AvFZZmQe/BfopYCtghCKKVBUSetZ4QKcyA0pY6/4Gw8Pv8w==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } } }, "@gulp-sourcemaps/map-sources": { @@ -53,39 +39,46 @@ "integrity": "sha512-BdN2PXxOFnTXFcyONPW6t0fHjz2fvRZHVMFpaS0wYr+Y8fWEaNOs4V8LEu/fpzQlMx+ahdndgTaGTwPC+J/EeA==", "dev": true, "requires": { - "@types/express": "4.0.39", + "@types/express": "4.11.1", "@types/node": "8.0.53" } }, "@types/bson": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/bson/-/bson-1.0.5.tgz", - "integrity": "sha512-PTrbsXNuvh2Wg+xALmsb/y8iUgfvAdDKw5vuyhHXleQbKgD8JbM8bbS+VVlb4dLVWkmxPUU+OEpHM7ZwSjQdgQ==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/bson/-/bson-1.0.8.tgz", + "integrity": "sha512-PMa4nkRhLaqwsXQDDTzGbTyCIpej0ERznyAP9fyuGnlsmUbcC4Y25mdqjibYjkOPNyK/BWWUKneruaKHcS3Q8g==", "dev": true, "requires": { "@types/node": "8.0.53" } }, "@types/chai": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.0.8.tgz", - "integrity": "sha512-m812CONwdZn/dMzkIJEY0yAs4apyTkTORgfB2UsMOxgkUbC205AHnm4T8I0I5gPg9MHrFc1dJ35iS75c0CJkjg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.2.tgz", + "integrity": "sha512-D8uQwKYUw2KESkorZ27ykzXgvkDJYXVEihGklgfp5I4HUP8D6IxtcdLTMB1emjQiWzV7WZ5ihm1cxIzVwjoleQ==", "dev": true }, "@types/chai-http": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/chai-http/-/chai-http-3.0.3.tgz", - "integrity": "sha512-dr9S1Xt3s1oIYO3bgfPGkYNyiaUSkubTqbdGqbki41Lad7CGgAyKHuvcBbtSrpLnlkxyPlC8UG4VK6nyqCGb+w==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/chai-http/-/chai-http-3.0.4.tgz", + "integrity": "sha512-vfCOp/hd3A3Dd0/R5xOl7NraQynZ/jem02KdhokmUzW59CiPtqmISe+evshyuVicYQCHJdn+Tj9+juF/HsmRMQ==", "dev": true, "requires": { - "@types/chai": "4.0.8", - "@types/node": "8.0.53" + "@types/chai": "4.1.2", + "@types/node": "8.0.53", + "@types/superagent": "3.5.7" } }, + "@types/events": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", + "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==", + "dev": true + }, "@types/express": { - "version": "4.0.39", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.0.39.tgz", - "integrity": "sha512-dBUam7jEjyuEofigUXCtublUHknRZvcRgITlGsTbFgPvnTwtQUt2NgLakbsf+PsGo/Nupqr3IXCYsOpBpofyrA==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.11.1.tgz", + "integrity": "sha512-ttWle8cnPA5rAelauSWeWJimtY2RsUf2aspYZs7xPHiWgOlPn6nnUfBMtrkcnjFJuIHJF4gNOdVvpLK2Zmvh6g==", "dev": true, "requires": { "@types/body-parser": "1.16.8", @@ -102,40 +95,57 @@ "@types/node": "8.0.53" } }, + "@types/fancy-log": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@types/fancy-log/-/fancy-log-1.3.0.tgz", + "integrity": "sha512-mQjDxyOM1Cpocd+vm1kZBP7smwKZ4TNokFeds9LV7OZibmPJFEzY3+xZMrKfUdNT71lv8GoCPD6upKwHxubClw==", + "dev": true + }, "@types/fs-extra": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-4.0.5.tgz", - "integrity": "sha512-tIG0GpHum5IFb8Qze/cSv0w/0gNzHB+MUDftTQaxenx46z50g51/MPkNLssLz9+uZLzCDd35bT9qtWOTXZ21Gw==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.2.tgz", + "integrity": "sha512-Q3FWsbdmkQd1ib11A4XNWQvRD//5KpPoGawA8aB2DR7pWKoW9XQv3+dGxD/Z1eVFze23Okdo27ZQytVFlweKvQ==", + "dev": true, + "requires": { + "@types/node": "8.0.53" + } + }, + "@types/glob": { + "version": "5.0.35", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-5.0.35.tgz", + "integrity": "sha512-wc+VveszMLyMWFvXLkloixT4n0harUIVZjnpzztaZ0nKLuul7Z32iMt2fUFGAaZ4y1XWjFRMtCI5ewvyh4aIeg==", "dev": true, "requires": { + "@types/events": "1.2.0", + "@types/minimatch": "3.0.3", "@types/node": "8.0.53" } }, "@types/handlebars": { - "version": "4.0.31", - "resolved": "https://registry.npmjs.org/@types/handlebars/-/handlebars-4.0.31.tgz", - "integrity": "sha1-p/umb6/kJxOu6I7sqNuRGS7+bnI=", + "version": "4.0.36", + "resolved": "https://registry.npmjs.org/@types/handlebars/-/handlebars-4.0.36.tgz", + "integrity": "sha512-LjNiTX7TY7wtuC6y3QwC93hKMuqYhgV9A1uXBKNvZtVC8ZvyWAjZkJ5BvT0K7RKqORRYRLMrqCxpw5RgS+MdrQ==", "dev": true }, "@types/highlight.js": { - "version": "9.1.8", - "resolved": "https://registry.npmjs.org/@types/highlight.js/-/highlight.js-9.1.8.tgz", - "integrity": "sha1-0ifxi8uPPxh+FpZfJESFmgRol1g=", + "version": "9.12.2", + "resolved": "https://registry.npmjs.org/@types/highlight.js/-/highlight.js-9.12.2.tgz", + "integrity": "sha512-y5x0XD/WXDaGSyiTaTcKS4FurULJtSiYbGTeQd0m2LYZGBcZZ/7fM6t5H/DzeUF+kv8y6UfmF6yJABQsHcp9VQ==", "dev": true }, "@types/jsonwebtoken": { - "version": "7.2.4", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-7.2.4.tgz", - "integrity": "sha512-EOPpfvAypsg9oNAY2XN5XFqCySxXPfHQOOYq1CEIhV+5L6QwcsOZkzkrk93fJ4pZ80flZqsQXsz9KyVFgVpiBw==", + "version": "7.2.7", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-7.2.7.tgz", + "integrity": "sha512-lq9X76APpxGJDUe1VptL1P5GrogqhPCH+SDy94+gaBJw7Hhj6hwrVC6zuxAx2GrgktkBuwydESZBvPfrdBoOEg==", "dev": true, "requires": { "@types/node": "8.0.53" } }, "@types/lodash": { - "version": "4.14.74", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.74.tgz", - "integrity": "sha512-BZknw3E/z3JmCLqQVANcR17okqVTPZdlxvcIz0fJiJVLUCbSH1hK3zs9r634PVSmrzAxN+n/fxlVRiYoArdOIQ==", + "version": "4.14.104", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.104.tgz", + "integrity": "sha512-ufQcVg4daO8xQ5kopxRHanqFdL4AI7ondQkV+2f+7mz3gvp0LkBx2zBRC6hfs3T87mzQFmf5Fck7Fi145Ul6NQ==", "dev": true }, "@types/marked": { @@ -151,34 +161,36 @@ "dev": true }, "@types/minimatch": { - "version": "2.0.29", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-2.0.29.tgz", - "integrity": "sha1-UALhT3Xi1x5WQoHfBDHIwbSio2o=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", "dev": true }, "@types/mocha": { - "version": "2.2.44", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.44.tgz", - "integrity": "sha512-k2tWTQU8G4+iSMvqKi0Q9IIsWAp/n8xzdZS4Q4YVIltApoMA00wFBFdlJnmoaK1/z7B0Cy0yPe6GgXteSmdUNw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.0.tgz", + "integrity": "sha512-YeDiSEzznwZwwp766SJ6QlrTyBYUGPSIwmREHVTmktUYiT/WADdWtpt9iH0KuUSf8lZLdI4lP0X6PBzPo5//JQ==", "dev": true }, "@types/mongodb": { - "version": "2.2.16", - "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-2.2.16.tgz", - "integrity": "sha512-DoxB+i3LcZzq925yp5rwsC0YwffeZ/tybAWUbnDOvUSCb5AG6wdHU+ggPdX8qVeEZMPzPgO9wfrzyBK7o9FEGA==", + "version": "3.0.18", + "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.0.18.tgz", + "integrity": "sha512-0LflLyhsCEMOSiqcTb7QYl/VQv3m0acU0ouI7sPmyNmL4P1JNldiJZsNcmIliLyHFaKTQ3Rb+BJtUBLzlVhKzg==", "dev": true, "requires": { - "@types/bson": "1.0.5", + "@types/bson": "1.0.8", + "@types/events": "1.2.0", "@types/node": "8.0.53" } }, "@types/mongoose": { - "version": "4.7.28", - "resolved": "https://registry.npmjs.org/@types/mongoose/-/mongoose-4.7.28.tgz", - "integrity": "sha512-XbMRVMp6AqTI9n4dvHDQxfq3t5PBMeZVx3BfRaQLhz2fa8JhdmQUi2AVWcJD7ejmRS9RqYP5wl9Uu2UzT/LiUw==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/@types/mongoose/-/mongoose-5.0.12.tgz", + "integrity": "sha512-uRy65g/muXayu6sZm9irHQymwvBveMP5kIqYzqFLGGzPHh5m9YW/Yl7e/XKNgyWJ5+4XoE5eVsGEmovLFqoqSg==", "dev": true, "requires": { - "@types/mongodb": "2.2.16", + "@types/events": "1.2.0", + "@types/mongodb": "3.0.18", "@types/node": "8.0.53" } }, @@ -188,51 +200,52 @@ "integrity": "sha512-E9qFi0seOkdlQnCTPv54brNfGWeFdRaEhI5tSue4pdx/V+xfxvMETsxXhOEcj1cYL+0n/jcTEmj/jD2gjzCwMg==", "dev": true, "requires": { - "@types/express": "4.0.39" + "@types/express": "4.11.1" } }, "@types/node": { "version": "8.0.53", "resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.53.tgz", - "integrity": "sha512-54Dm6NwYeiSQmRB1BLXKr5GELi0wFapR1npi8bnZhEcu84d/yQKqnwwXQ56hZ0RUbTG6L5nqDZaN3dgByQXQRQ==", - "dev": true + "integrity": "sha512-54Dm6NwYeiSQmRB1BLXKr5GELi0wFapR1npi8bnZhEcu84d/yQKqnwwXQ56hZ0RUbTG6L5nqDZaN3dgByQXQRQ==" }, "@types/nodemailer": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-4.3.1.tgz", - "integrity": "sha512-6Y+W44okdSco6w3zhahnwJXbONrCrfgi0LnF/aQAdHFnrel4VYwfF0u81NNKHTbweKacu2TVDv/2BIZhgutxIA==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-4.6.0.tgz", + "integrity": "sha512-DWG172izmWXfShUm2Lm6nVght5TxDI1cx2cKiGPeu2f66yTnn0QY7WhC9OSybdPoxGu7UbRXNuIkIzB+NE648A==", "dev": true, "requires": { + "@types/events": "1.2.0", "@types/node": "8.0.53" } }, "@types/passport": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@types/passport/-/passport-0.4.1.tgz", - "integrity": "sha512-oArDlvZZPfoB1ppwz1N0CdevSkZa7Gv9dkABUj4JFfvB/PKvuMf+h4JSrIShLbmXXIC9XQQQVTVU42lxOGJhrA==", + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-0.4.5.tgz", + "integrity": "sha512-Ow5akVXwEZlOPCWGbEGy0GX4ocdwKz7JJH1K+BMd/BSOxmJTo2obH2AKbsgcncQvw5z7AGopdIu1Ap/j9sMRnQ==", "dev": true, "requires": { - "@types/express": "4.0.39" + "@types/express": "4.11.1" } }, "@types/passport-jwt": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/passport-jwt/-/passport-jwt-3.0.0.tgz", - "integrity": "sha512-se7XVNvVWFRyoiLUpRoMxISk0pToiCmUmCMtRmxEKSP4nVcQxdJgZxz7IRsHDeAYO33jQbggtJNaeUAoKLV8uw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/passport-jwt/-/passport-jwt-3.0.1.tgz", + "integrity": "sha512-JwF9U/Rmr6YicHSu/MITmHNDy2KeiedxKW2bhz6wZts3y4cq48NiN0UD98zO56TyM5Vm6BpyjFxcs6jh68ni/A==", "dev": true, "requires": { - "@types/express": "4.0.39", + "@types/express": "4.11.1", + "@types/jsonwebtoken": "7.2.7", "@types/passport-strategy": "0.2.32" } }, "@types/passport-local": { - "version": "1.0.32", - "resolved": "https://registry.npmjs.org/@types/passport-local/-/passport-local-1.0.32.tgz", - "integrity": "sha512-LZm3T9JDvnC6vDBMsueWVFDg2pSccy2iObgqWFtenPwa/MpHcSzOhADxzNyOwPztbRps2hPLWGH9ApS6nnST1Q==", + "version": "1.0.33", + "resolved": "https://registry.npmjs.org/@types/passport-local/-/passport-local-1.0.33.tgz", + "integrity": "sha512-+rn6ZIxje0jZ2+DAiWFI8vGG7ZFKB0hXx2cUdMmudSWsigSq6ES7Emso46r4HJk0qCgrZVfI8sJiM7HIYf4SbA==", "dev": true, "requires": { - "@types/express": "4.0.39", - "@types/passport": "0.4.1", + "@types/express": "4.11.1", + "@types/passport": "0.4.5", "@types/passport-strategy": "0.2.32" } }, @@ -242,16 +255,17 @@ "integrity": "sha512-EZGW2UdmnDrHkLbyO2I1yo1lZuWB0Hs142Wfbg9HLED7m3e6JGUQlMkZbL2bgN6cNMW4fPaFj+uUX7EmLtSY7A==", "dev": true, "requires": { - "@types/express": "4.0.39", - "@types/passport": "0.4.1" + "@types/express": "4.11.1", + "@types/passport": "0.4.5" } }, "@types/raven": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@types/raven/-/raven-2.1.2.tgz", - "integrity": "sha512-jIDsw4Lci7z7Ay1VfDI8AHhoolyvV3sdUibMqFIzHcnIUon/or/ROXKvbPowwY/VkMXlF7CSs8UG9ZLix4p38A==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@types/raven/-/raven-2.5.1.tgz", + "integrity": "sha512-pWEyOzD1VUXqVpDaZGsa1LnhZqXwTjMwVftNVU+nj7QOvRj+HvwUc4aVtljoj3CWGiBPUZyCTOHrtzvx56IQRQ==", "dev": true, "requires": { + "@types/events": "1.2.0", "@types/node": "8.0.53" } }, @@ -265,25 +279,43 @@ "@types/mime": "2.0.0" } }, + "@types/sharp": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@types/sharp/-/sharp-0.17.8.tgz", + "integrity": "sha512-wQGqStKMaSInhLCCGyArCD967bNGZ96jtfTAjiMkDCX+7LF7mBIch5BwVVmPgSZGiyb7Wo7JdIvwXHvIDzWVvA==", + "requires": { + "@types/node": "8.0.53" + } + }, "@types/shelljs": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.7.0.tgz", - "integrity": "sha1-IpwVfGvB5n1rmQ5sXhjb0v9Yz/A=", + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.7.8.tgz", + "integrity": "sha512-M2giRw93PxKS7YjU6GZjtdV9HASdB7TWqizBXe4Ju7AqbKlWvTr0gNO92XH56D/gMxqD/jNHLNfC5hA34yGqrQ==", + "dev": true, + "requires": { + "@types/glob": "5.0.35", + "@types/node": "8.0.53" + } + }, + "@types/superagent": { + "version": "3.5.7", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-3.5.7.tgz", + "integrity": "sha512-zvDPQHA/M8f8SqU3jgQ0PFgaO0FV+IarGwhRm8dy0CIPRi5on187IhkOJFTUT3O03C/vqjZ3jlhOichhw3RVng==", "dev": true, "requires": { "@types/node": "8.0.53" } }, "@types/validator": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-6.3.0.tgz", - "integrity": "sha512-fUc+9BEr1WWW8wVRl5I/pyRDGZNe9nH06kOzlGH3eN7N8VVPW/zSrE0Vdca6G2sRCVmIN/XuOenbmldAAyTYaw==", + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-9.4.1.tgz", + "integrity": "sha512-Y8UyLZvBPgckGhEIFCGBPj1tsRbpcZn4rbAp7lUxC3EW/nDR2V6t9LltE+mvDJxQQ+Bg3saE3UAwn6lsG5O1yQ==", "dev": true }, "@types/winston": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/@types/winston/-/winston-2.3.7.tgz", - "integrity": "sha512-jNhbkxPtt9xbzvihfA0OavjJbpCIyTDSmwE03BVXgCKcz9lwNsq4cg2wsNkY4Av5eH35ttBArhYtVJa6CIrg2A==", + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/@types/winston/-/winston-2.3.9.tgz", + "integrity": "sha512-zzruYOEtNgfS3SBjcij1F6HlH6My5n8WrBNhP3fzaRM22ba70QBC2ATs18jGr88Fy43c0z8vFJv5wJankfxv2A==", "dev": true, "requires": { "@types/node": "8.0.53" @@ -295,18 +327,33 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "accepts": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", - "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", "requires": { - "mime-types": "2.1.17", + "mime-types": "2.1.18", "negotiator": "0.6.1" + }, + "dependencies": { + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "requires": { + "mime-db": "1.33.0" + } + } } }, "acorn": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", - "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz", + "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==", "dev": true }, "ajv": { @@ -379,11 +426,47 @@ } } }, + "ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-cyan": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz", + "integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, "ansi-escapes": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=" }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-red": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", + "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -394,6 +477,17 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true + }, + "ansicolor": { + "version": "1.1.71", + "resolved": "https://registry.npmjs.org/ansicolor/-/ansicolor-1.1.71.tgz", + "integrity": "sha1-OLv5fbKC7bFGLcsjQAESQHqUhuM=" + }, "anymatch": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", @@ -412,7 +506,7 @@ "apidoc-core": "0.8.3", "fs-extra": "3.0.1", "lodash": "4.17.4", - "markdown-it": "8.4.0", + "markdown-it": "8.4.1", "nomnom": "1.8.1", "winston": "2.3.1" }, @@ -506,6 +600,15 @@ "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.0.1.tgz", "integrity": "sha1-zWLc+OT9WkF+/GZNLlsQZTxlG0Y=" }, + "append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", + "dev": true, + "requires": { + "buffer-equal": "1.0.0" + } + }, "append-field": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/append-field/-/append-field-0.1.0.tgz", @@ -517,9 +620,9 @@ "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" }, "archiver": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.0.tgz", - "integrity": "sha1-0t8ujVdzqCwdzOklzMQUUOqZmv0=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", + "integrity": "sha1-/2YrSnggFJSj7lRNOjP+dJZQnrw=", "requires": { "archiver-utils": "1.3.0", "async": "2.6.0", @@ -618,12 +721,6 @@ "is-extended": "0.0.10" } }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true - }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -1404,6 +1501,13 @@ "requires": { "nan": "2.6.2", "node-pre-gyp": "0.6.36" + }, + "dependencies": { + "nan": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.6.2.tgz", + "integrity": "sha1-5P805slf37WuzAjeZZb0NgWn20U=" + } } }, "bcrypt-pbkdf": { @@ -1427,11 +1531,33 @@ "integrity": "sha1-muuabF6IY4qtFx4Wf1kAq+JINdA=" }, "bl": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.1.tgz", - "integrity": "sha1-ysMo977kVzDUBLaSID/LWQ4XLV4=", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", "requires": { - "readable-stream": "2.3.3" + "readable-stream": "2.3.5", + "safe-buffer": "5.1.1" + }, + "dependencies": { + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "readable-stream": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", + "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + } } }, "block-stream": { @@ -1587,15 +1713,21 @@ "dev": true }, "bson": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.4.tgz", - "integrity": "sha1-k8ENOeqltYQVy8QFLz5T5WKwtyw=" + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.6.tgz", + "integrity": "sha512-D8zmlb46xfuK2gGvKmUjIklQEouN2nQ0LEHHeZ/NoHM2LDiMk2EYzZ5Ntw/Urk+bgMDosOZxaRzXxvhI5TcAVQ==" }, "buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" }, + "buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", + "dev": true + }, "buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", @@ -1680,24 +1812,6 @@ "dev": true, "optional": true }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true, - "requires": { - "camelcase": "2.1.1", - "map-obj": "1.0.1" - }, - "dependencies": { - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - } - } - }, "capture-stack-trace": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", @@ -1744,16 +1858,16 @@ } }, "chai-http": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chai-http/-/chai-http-3.0.0.tgz", - "integrity": "sha1-VGDYA24fGhKwtbXL1Snm3B0x60s=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/chai-http/-/chai-http-4.0.0.tgz", + "integrity": "sha512-R30Lj3JHHPhknOyurh09ZEBgyO4iSSeTjbLmyLvTr88IFC+zwRjAmaxBwj9TbEAGi0IV2uW+RHaTxeah5rdSaQ==", "dev": true, "requires": { - "cookiejar": "2.0.6", - "is-ip": "1.0.0", + "cookiejar": "2.1.1", + "is-ip": "2.0.0", "methods": "1.1.2", "qs": "6.5.1", - "superagent": "2.3.0" + "superagent": "3.8.2" } }, "chalk": { @@ -1768,6 +1882,11 @@ "supports-color": "2.0.0" } }, + "charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=" + }, "charset-detector": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/charset-detector/-/charset-detector-0.0.2.tgz", @@ -1786,6 +1905,7 @@ "requires": { "anymatch": "1.3.2", "async-each": "1.0.1", + "fsevents": "1.2.0", "glob-parent": "2.0.0", "inherits": "2.0.3", "is-binary-path": "1.0.1", @@ -1794,10 +1914,15 @@ "readdirp": "2.1.0" } }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" + }, "class-transformer": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.1.8.tgz", - "integrity": "sha512-qniRyjtvDPEXFspXfjrYerYy75pqwOIN4IUf2/MPHzZ3zVB7Cssq7dKSNZzEp6G1DH8tDk5gKY+KFxtlkf03qQ==" + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.1.9.tgz", + "integrity": "sha512-KV0IteiRl95OZ9UzbuPj8RhckuHA4JTC+Q+ZbKTYPsmvB0GgPRG7JBEXiVhBq/U050OVRku4N5t0rSMHw8vDWw==" }, "class-utils": { "version": "0.3.5", @@ -1887,17 +2012,18 @@ } }, "class-validator": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.7.3.tgz", - "integrity": "sha512-aRRlS1WlQ+52aHlmDCDX5dLwtpbg9is7i9yYhzQosTAVs86nX0Um8hb7ChTwMn7jfpyxxjAZpBrlrAc2tqNpYA==", + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.8.4.tgz", + "integrity": "sha512-aOBVEzRNvnulvb615EK7xnVICOmUt06zEtOCeSA93IhWhRIBpY/iGlVZEmHiOvLHtY4DH4JwJK1zNabv3YZcqg==", "requires": { - "validator": "7.2.0" + "ansicolor": "1.1.71", + "validator": "9.2.0" }, "dependencies": { "validator": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-7.2.0.tgz", - "integrity": "sha512-c8NGTUYeBEcUIGeMppmNVKHE7wwfm3mYbNZxV+c5mlv9fDHI7Ad3p07qfNrn/CvpdkK2k61fOLRO2sTEhgQXmg==" + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-9.2.0.tgz", + "integrity": "sha512-6Ij4Eo0KM4LkR0d0IegOwluG5453uqT5QyF5SV5Ezvm8/zmkKI/L4eoraafZGlZPC9guLkwKzgypcw8VGWWnGA==" } } }, @@ -1947,12 +2073,52 @@ "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", "dev": true }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true + }, "clone-stats": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", "dev": true }, + "cloneable-readable": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", + "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "process-nextick-args": "2.0.0", + "readable-stream": "2.3.5" + }, + "dependencies": { + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "readable-stream": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", + "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + } + } + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -1973,11 +2139,19 @@ "object-visit": "1.0.1" } }, + "color": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", + "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", + "requires": { + "color-convert": "1.9.1", + "color-string": "1.5.2" + } + }, "color-convert": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", - "dev": true, "requires": { "color-name": "1.1.3" } @@ -1985,7 +2159,21 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "color-string": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.2.tgz", + "integrity": "sha1-JuRYFLw8mny9Z1FkikFDRRSnc6k=", + "requires": { + "color-name": "1.1.3", + "simple-swizzle": "0.2.2" + } + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", "dev": true }, "colors": { @@ -2002,13 +2190,10 @@ } }, "commander": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", - "dev": true, - "requires": { - "graceful-readlink": "1.0.1" - } + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", + "dev": true }, "component-emitter": { "version": "1.2.1", @@ -2087,9 +2272,9 @@ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, "cookiejar": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.0.6.tgz", - "integrity": "sha1-Cr81atANHFohnYjURRgEbdAmrP4=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.1.tgz", + "integrity": "sha1-Qa1XsbVVlR7BcUEqgZQrHoIA00o=", "dev": true }, "copy-descriptor": { @@ -2109,14 +2294,14 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "coveralls": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.0.tgz", - "integrity": "sha512-ZppXR9y5PraUOrf/DzHJY6gzNUhXYE3b9D43xEXs4QYZ7/Oe0Gy0CS+IPKWFfvQFXB3RG9QduaQUFehzSpGAFw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.1.tgz", + "integrity": "sha512-FAzXwiDOYLGDWH+zgoIA+8GbWv50hlx+kpEJyvzLKOdnIBv9uWoVl4DhqGgyUHpiRjAlF8KYZSipWXYtllWH6Q==", "dev": true, "requires": { "js-yaml": "3.10.0", "lcov-parse": "0.0.10", - "log-driver": "1.2.5", + "log-driver": "1.2.7", "minimist": "1.2.0", "request": "2.83.0" }, @@ -2175,6 +2360,11 @@ } } }, + "crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=" + }, "cryptiles": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", @@ -2240,15 +2430,6 @@ } } }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, - "requires": { - "array-find-index": "1.0.2" - } - }, "cycle": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", @@ -2260,7 +2441,7 @@ "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "dev": true, "requires": { - "es5-ext": "0.10.37" + "es5-ext": "0.10.41" } }, "dargs": { @@ -2302,13 +2483,13 @@ } }, "debug-fabulous": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-0.2.1.tgz", - "integrity": "sha512-u0TV6HcfLsZ03xLBhdhSViQMldaiQ2o+8/nSILaXkuNSWvxkx66vYJUAam0Eu7gAilJRX/69J4kKdqajQPaPyw==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.0.0.tgz", + "integrity": "sha512-dsd50qQ1atDeurcxL7XOjPp4nZCGZzWIONDujDXzl1atSyC3hMbZD+v6440etw+Vt0Pr8ce4TQzHfX3KZM05Mw==", "dev": true, "requires": { "debug": "3.1.0", - "memoizee": "0.4.11", + "memoizee": "0.4.12", "object-assign": "4.1.1" }, "dependencies": { @@ -2339,6 +2520,14 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "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=", + "requires": { + "mimic-response": "1.0.0" + } + }, "deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", @@ -2368,6 +2557,16 @@ "clone": "1.0.3" } }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "dev": true, + "requires": { + "foreach": "2.0.5", + "object-keys": "1.0.11" + } + }, "define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", @@ -2411,6 +2610,11 @@ "repeating": "2.0.1" } }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + }, "detect-newline": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", @@ -2450,9 +2654,9 @@ } }, "diff": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", - "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", "dev": true }, "dot-prop": { @@ -2546,9 +2750,9 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "encodeurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", - "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=" + "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.0", @@ -2573,13 +2777,14 @@ } }, "es5-ext": { - "version": "0.10.37", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz", - "integrity": "sha1-DudB0Ui4AGm6J9AgOTdWryV978M=", + "version": "0.10.41", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.41.tgz", + "integrity": "sha512-MYK02wXfwTMie5TEJWPolgOsXEmz7wKCQaGzgmRjZOoV6VLG8I5dSv2bn6AOClXhK64gnSQTQ9W9MKvx87J4gw==", "dev": true, "requires": { "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" + "es6-symbol": "3.1.1", + "next-tick": "1.0.0" } }, "es6-iterator": { @@ -2589,7 +2794,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.37", + "es5-ext": "0.10.41", "es6-symbol": "3.1.1" } }, @@ -2605,7 +2810,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.37" + "es5-ext": "0.10.41" } }, "es6-weak-map": { @@ -2615,7 +2820,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.37", + "es5-ext": "0.10.41", "es6-iterator": "2.0.3", "es6-symbol": "3.1.1" } @@ -2690,7 +2895,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.37" + "es5-ext": "0.10.41" } }, "event-stream": { @@ -2709,9 +2914,9 @@ } }, "execa": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.6.3.tgz", - "integrity": "sha1-V7aaWU8IF1nGnlNw8NF7nLEWWP4=", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", + "integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=", "dev": true, "requires": { "cross-spawn": "5.1.0", @@ -2744,12 +2949,17 @@ "fill-range": "2.2.3" } }, + "expand-template": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.1.0.tgz", + "integrity": "sha512-kkjwkMqj0h4w/sb32ERCDxCQkREMCAgS39DscDnSwDsbxnwwM1BTZySdC3Bn1lhY7vL08n9GoO/fVTynjDgRyQ==" + }, "express": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.16.2.tgz", - "integrity": "sha1-41xt/i1kt9ygpc1PIXgb4ymeB2w=", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", + "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", "requires": { - "accepts": "1.3.4", + "accepts": "1.3.5", "array-flatten": "1.1.1", "body-parser": "1.18.2", "content-disposition": "0.5.2", @@ -2757,39 +2967,61 @@ "cookie": "0.3.1", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "1.1.1", - "encodeurl": "1.0.1", + "depd": "1.1.2", + "encodeurl": "1.0.2", "escape-html": "1.0.3", "etag": "1.8.1", - "finalhandler": "1.1.0", + "finalhandler": "1.1.1", "fresh": "0.5.2", "merge-descriptors": "1.0.1", "methods": "1.1.2", "on-finished": "2.3.0", "parseurl": "1.3.2", "path-to-regexp": "0.1.7", - "proxy-addr": "2.0.2", + "proxy-addr": "2.0.3", "qs": "6.5.1", "range-parser": "1.2.0", "safe-buffer": "5.1.1", - "send": "0.16.1", - "serve-static": "1.13.1", + "send": "0.16.2", + "serve-static": "1.13.2", "setprototypeof": "1.1.0", - "statuses": "1.3.1", - "type-is": "1.6.15", + "statuses": "1.4.0", + "type-is": "1.6.16", "utils-merge": "1.0.1", "vary": "1.1.2" }, "dependencies": { + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "requires": { + "mime-db": "1.33.0" + } + }, "setprototypeof": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" }, - "statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.1.18" + } } } }, @@ -2905,24 +3137,17 @@ } }, "finalhandler": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", - "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", "requires": { "debug": "2.6.9", - "encodeurl": "1.0.1", + "encodeurl": "1.0.2", "escape-html": "1.0.3", "on-finished": "2.3.0", "parseurl": "1.3.2", - "statuses": "1.3.1", + "statuses": "1.4.0", "unpipe": "1.0.0" - }, - "dependencies": { - "statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" - } } }, "find-index": { @@ -2970,6 +3195,16 @@ "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", "dev": true }, + "flush-write-stream": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", + "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3" + } + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -2983,6 +3218,12 @@ "for-in": "1.0.2" } }, + "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", @@ -2999,9 +3240,9 @@ } }, "formidable": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.1.1.tgz", - "integrity": "sha1-lriIb3w8NQi5Mta9cMTTqI818ak=", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz", + "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==", "dev": true }, "forwarded": { @@ -3029,16 +3270,39 @@ "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", "dev": true }, + "fs-copy-file-sync": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-copy-file-sync/-/fs-copy-file-sync-1.1.0.tgz", + "integrity": "sha512-Pv0mBC3NXW6ql1sdG//3GL6TsxEoih6nVq8rO4PFqX4lo2C9soZvn8iiL8K0TUEtimtFKFvFrQbnWfJ0uazvsA==" + }, "fs-extra": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", - "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", + "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", "requires": { "graceful-fs": "4.1.11", "jsonfile": "4.0.0", "universalify": "0.1.1" } }, + "fs-minipass": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", + "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", + "requires": { + "minipass": "2.2.4" + } + }, + "fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "through2": "2.0.3" + } + }, "fs-readdir-recursive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", @@ -3049,27 +3313,808 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, - "fstream": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", - "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", - "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.2" - } - }, - "fstream-ignore": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", - "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", + "fsevents": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.0.tgz", + "integrity": "sha512-ROrBIbmw4ulxmQTwYAAGyN/0xgIOAFd6gX/K3F1aGLP/K5KxkubrlGISMV5EEWEB7qtiEdE0HpaqvMMHR+Ib6w==", + "optional": true, "requires": { - "fstream": "1.0.11", + "nan": "2.10.0", + "node-pre-gyp": "0.9.1" + }, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "bundled": true, + "optional": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "aproba": { + "version": "1.1.1", + "bundled": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.2.9" + } + }, + "asn1": { + "version": "0.2.3", + "bundled": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true + }, + "balanced-match": { + "version": "0.4.2", + "bundled": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.7", + "bundled": true, + "requires": { + "balanced-match": "0.4.2", + "concat-map": "0.0.1" + } + }, + "buffer-shims": { + "version": "1.0.0", + "bundled": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true + }, + "co": { + "version": "4.6.0", + "bundled": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "debug": { + "version": "2.6.8", + "bundled": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true, + "optional": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true + }, + "extsprintf": { + "version": "1.0.2", + "bundled": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.15" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.1" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "optional": true, + "requires": { + "aproba": "1.1.1", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.0", + "sshpk": "1.13.0" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.4", + "bundled": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true + }, + "jodid25519": { + "version": "1.0.2", + "bundled": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true + }, + "jsprim": { + "version": "1.4.0", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "mime-db": { + "version": "1.27.0", + "bundled": true + }, + "mime-types": { + "version": "2.1.15", + "bundled": true, + "requires": { + "mime-db": "1.27.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true + }, + "node-pre-gyp": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.9.1.tgz", + "integrity": "sha1-8RwHUW3ZL4cZnbx+GDjqt81WyeA=", + "optional": true, + "requires": { + "detect-libc": "1.0.2", + "mkdirp": "0.5.1", + "needle": "2.2.0", + "nopt": "4.0.1", + "npm-packlist": "1.1.10", + "npmlog": "4.1.0", + "rc": "1.2.1", + "rimraf": "2.6.1", + "semver": "5.3.0", + "tar": "4.4.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "optional": true + }, + "tar": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.1.tgz", + "integrity": "sha512-O+v1r9yN4tOsvl90p5HAP4AEqbYhx4036AGMm075fH9F8Qwi3oJ+v4u50FkT/KkvywNGtwkk0zRI+8eYm1X/xg==", + "optional": true, + "requires": { + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.2.4", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.1", + "yallist": "3.0.2" + } + } + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "optional": true, + "requires": { + "abbrev": "1.1.0", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.0", + "bundled": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true + }, + "qs": { + "version": "6.4.0", + "bundled": true + }, + "rc": { + "version": "1.2.1", + "bundled": true, + "optional": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.2.9", + "bundled": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.1", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.15", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.0.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.6.0", + "uuid": "3.0.1" + } + }, + "rimraf": { + "version": "2.6.1", + "bundled": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.0.1", + "bundled": true + }, + "semver": { + "version": "5.3.0", + "bundled": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "optional": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.0", + "bundled": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jodid25519": "1.0.2", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "stringstream": { + "version": "0.0.5", + "bundled": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.0", + "bundled": true, + "requires": { + "debug": "2.6.8", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.2.9", + "rimraf": "2.6.1", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.2", + "bundled": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "uuid": { + "version": "3.0.1", + "bundled": true + }, + "verror": { + "version": "1.3.6", + "bundled": true, + "requires": { + "extsprintf": "1.0.2" + } + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "yallist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", + "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=", + "optional": true + } + } + }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", + "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", + "requires": { + "fstream": "1.0.11", "inherits": "2.0.3", "minimatch": "3.0.4" } }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, "gauge": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", @@ -3105,12 +4150,6 @@ "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "dev": true }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - }, "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", @@ -3131,6 +4170,11 @@ "assert-plus": "1.0.0" } }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" + }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", @@ -3349,16 +4393,10 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true - }, "growl": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", - "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==", "dev": true }, "gulp": { @@ -3397,42 +4435,161 @@ } }, "gulp-apidoc": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/gulp-apidoc/-/gulp-apidoc-0.2.6.tgz", - "integrity": "sha1-EedQrRln6/J8BFShVDsRQj/5fzQ=", + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/gulp-apidoc/-/gulp-apidoc-0.2.7.tgz", + "integrity": "sha512-KBCN3Jn1lpM8HP+pJVAPDkzC7Ny3vEz5kww2EluGm0VKP7nkKu2bapz+IsxNTWZltJrqn2OcazYzyfd5LXULIQ==", "dev": true, "requires": { + "ansi-colors": "1.1.0", "apidoc": "0.17.6", - "gulp-util": "3.0.8", - "object-assign": "4.1.1" + "fancy-log": "1.3.2", + "object-assign": "4.1.1", + "plugin-error": "1.0.1" + }, + "dependencies": { + "fancy-log": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", + "dev": true, + "requires": { + "ansi-gray": "0.1.1", + "color-support": "1.1.3", + "time-stamp": "1.1.0" + } + } } }, "gulp-istanbul": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/gulp-istanbul/-/gulp-istanbul-1.1.2.tgz", - "integrity": "sha512-53+BDhGlGNHYfeFh/mSXWhNu9wSFmE8qAEFj6ViMiWzTwI9pYxedUxMmGfigwaddsHHQxBl9TgnzUydrX84Kog==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gulp-istanbul/-/gulp-istanbul-1.1.3.tgz", + "integrity": "sha512-uMLSdqPDnBAV/B9rNyOgVMgrVC1tPbe+5GH6P13UOyxbRDT/w4sKYHWftPMA8j9om+NFvfeRlqpDXL2fixFWNA==", "dev": true, "requires": { - "gulp-util": "3.0.8", "istanbul": "0.4.5", "istanbul-threshold-checker": "0.2.1", "lodash": "4.17.4", + "plugin-error": "0.1.2", "through2": "2.0.3", "vinyl-sourcemaps-apply": "0.2.1" + }, + "dependencies": { + "arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-slice": "0.2.3" + } + }, + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", + "dev": true + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", + "dev": true, + "requires": { + "kind-of": "1.1.0" + } + }, + "kind-of": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", + "dev": true + }, + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", + "dev": true, + "requires": { + "ansi-cyan": "0.1.1", + "ansi-red": "0.1.1", + "arr-diff": "1.1.0", + "arr-union": "2.1.0", + "extend-shallow": "1.1.4" + } + } } }, "gulp-mocha": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/gulp-mocha/-/gulp-mocha-4.3.1.tgz", - "integrity": "sha1-d5ULQ7z/gWWVdnwHNOD9p9Fz3Nk=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/gulp-mocha/-/gulp-mocha-5.0.0.tgz", + "integrity": "sha512-NIjXZLqqcw9DXIEBcfm0sP1AUDlUJJeaK9EGCH2s6lSwo5NK/cEat0Vm7XelOkxZnWl0O5Za+aM6E4jyxWxTlw==", "dev": true, "requires": { "dargs": "5.1.0", - "execa": "0.6.3", - "gulp-util": "3.0.8", - "mocha": "3.5.3", + "execa": "0.8.0", + "mocha": "4.1.0", "npm-run-path": "2.0.2", + "plugin-error": "0.1.2", "through2": "2.0.3" + }, + "dependencies": { + "arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-slice": "0.2.3" + } + }, + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", + "dev": true + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", + "dev": true, + "requires": { + "kind-of": "1.1.0" + } + }, + "kind-of": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", + "dev": true + }, + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", + "dev": true, + "requires": { + "ansi-cyan": "0.1.1", + "ansi-red": "0.1.1", + "arr-diff": "1.1.0", + "arr-union": "2.1.0", + "extend-shallow": "1.1.4" + } + } } }, "gulp-nodemon": { @@ -3448,100 +4605,305 @@ } }, "gulp-plumber": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/gulp-plumber/-/gulp-plumber-1.1.0.tgz", - "integrity": "sha1-8SF2wtBCL2AwbCQv/2oBo5T6ugk=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gulp-plumber/-/gulp-plumber-1.2.0.tgz", + "integrity": "sha512-L/LJftsbKoHbVj6dN5pvMsyJn9jYI0wT0nMg3G6VZhDac4NesezecYTi8/48rHi+yEic3sUpw6jlSc7qNWh32A==", "dev": true, "requires": { - "gulp-util": "3.0.8", + "chalk": "1.1.3", + "fancy-log": "1.3.2", + "plugin-error": "0.1.2", "through2": "2.0.3" + }, + "dependencies": { + "arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-slice": "0.2.3" + } + }, + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", + "dev": true + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", + "dev": true, + "requires": { + "kind-of": "1.1.0" + } + }, + "fancy-log": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", + "dev": true, + "requires": { + "ansi-gray": "0.1.1", + "color-support": "1.1.3", + "time-stamp": "1.1.0" + } + }, + "kind-of": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", + "dev": true + }, + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", + "dev": true, + "requires": { + "ansi-cyan": "0.1.1", + "ansi-red": "0.1.1", + "arr-diff": "1.1.0", + "arr-union": "2.1.0", + "extend-shallow": "1.1.4" + } + } } }, "gulp-sourcemaps": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.1.tgz", - "integrity": "sha512-1qHCI3hdmsMdq/SUotxwUh/L8YzlI6J9zQ5ifNOtx4Y6KV5y5sGuORv1KZzWhuKtz/mXNh5xLESUtwC4EndCjA==", + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz", + "integrity": "sha1-y7IAhFCxvM5s0jv5gze+dRv24wo=", "dev": true, "requires": { "@gulp-sourcemaps/identity-map": "1.0.1", "@gulp-sourcemaps/map-sources": "1.0.0", - "acorn": "4.0.13", + "acorn": "5.5.3", "convert-source-map": "1.5.0", "css": "2.2.1", - "debug-fabulous": "0.2.1", + "debug-fabulous": "1.0.0", "detect-newline": "2.1.0", "graceful-fs": "4.1.11", - "source-map": "0.5.7", + "source-map": "0.6.1", "strip-bom-string": "1.0.0", - "through2": "2.0.3", - "vinyl": "1.2.0" + "through2": "2.0.3" }, "dependencies": { - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true } } }, "gulp-tslint": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/gulp-tslint/-/gulp-tslint-8.1.2.tgz", - "integrity": "sha512-0RNGqbp2TKPdbG+sWU3mNMXEMuF/noY1KS4+jd5lOStkvuFINkFL29dHX3IT1u+vVFD4Glwf+lkcdR2QMVNMzA==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/gulp-tslint/-/gulp-tslint-8.1.3.tgz", + "integrity": "sha512-KEP350N5B9Jg6o6jnyCyKVBPemJePYpMsGfIQq0G0ErvY7tw4Lrfb/y3L4WRf7ek0OsaE8nnj86w+lcLXW8ovw==", "dev": true, "requires": { - "gulp-util": "3.0.8", + "@types/fancy-log": "1.3.0", + "chalk": "2.3.1", + "fancy-log": "1.3.2", "map-stream": "0.0.7", + "plugin-error": "1.0.1", "through": "2.3.8" }, "dependencies": { + "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==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" + } + }, + "fancy-log": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", + "dev": true, + "requires": { + "ansi-gray": "0.1.1", + "color-support": "1.1.3", + "time-stamp": "1.1.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, "map-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", "dev": true + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } } } }, "gulp-typedoc": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/gulp-typedoc/-/gulp-typedoc-2.1.1.tgz", - "integrity": "sha512-3DW+ZgEUZpOHSySmVlksthS2W3t1Wn+/6HYq6QGAZdxoy9+8UHV5xYhl4aNAikISHbX8W4f4o2U7tLKS+f8jAw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/gulp-typedoc/-/gulp-typedoc-2.2.0.tgz", + "integrity": "sha512-yDBI4CK0CVRONXiI2EXx7rH732pPIXRr6HVlbH05Wbf9uU0/gJ1XiZCef4d43opHl6vA3QkWpM+8NxsMrcoD1w==", "dev": true, "requires": { + "ansi-colors": "1.1.0", "event-stream": "3.3.4", - "gulp-util": "3.0.8" + "fancy-log": "1.3.2", + "plugin-error": "0.1.2" + }, + "dependencies": { + "arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-slice": "0.2.3" + } + }, + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", + "dev": true + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", + "dev": true, + "requires": { + "kind-of": "1.1.0" + } + }, + "fancy-log": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", + "dev": true, + "requires": { + "ansi-gray": "0.1.1", + "color-support": "1.1.3", + "time-stamp": "1.1.0" + } + }, + "kind-of": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", + "dev": true + }, + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", + "dev": true, + "requires": { + "ansi-cyan": "0.1.1", + "ansi-red": "0.1.1", + "arr-diff": "1.1.0", + "arr-union": "2.1.0", + "extend-shallow": "1.1.4" + } + } } }, "gulp-typescript": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/gulp-typescript/-/gulp-typescript-3.2.3.tgz", - "integrity": "sha512-Np2sJXgtDUwIAoMtlJ9uXsVmpu1FWXlKZw164hLuo56uJa7qo5W2KZ0yAYiYH/HUsaz5L0O2toMOcLIokpFCPg==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp-typescript/-/gulp-typescript-4.0.2.tgz", + "integrity": "sha512-Hhbn5Aa2l3T+tnn0KqsG6RRJmcYEsr3byTL2nBpNBeAK8pqug9Od4AwddU4JEI+hRw7mzZyjRbB8DDWR6paGVA==", "dev": true, "requires": { - "gulp-util": "3.0.8", - "source-map": "0.5.7", + "ansi-colors": "1.1.0", + "plugin-error": "0.1.2", + "source-map": "0.6.1", "through2": "2.0.3", - "vinyl-fs": "2.4.4" + "vinyl": "2.1.0", + "vinyl-fs": "3.0.2" }, "dependencies": { - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", "dev": true, "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "arr-flatten": "1.1.0", + "array-slice": "0.2.3" + } + }, + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", + "dev": true + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", + "dev": true, + "requires": { + "kind-of": "1.1.0" } }, "glob-parent": { @@ -3555,56 +4917,21 @@ } }, "glob-stream": { - "version": "5.3.5", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", - "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", "dev": true, "requires": { "extend": "3.0.1", - "glob": "5.0.15", + "glob": "7.1.2", "glob-parent": "3.1.0", - "micromatch": "2.3.11", - "ordered-read-streams": "0.3.0", - "through2": "0.6.5", - "to-absolute-glob": "0.1.1", + "is-negated-glob": "1.0.0", + "ordered-read-streams": "1.0.1", + "pumpify": "1.4.0", + "readable-stream": "2.3.3", + "remove-trailing-separator": "1.1.0", + "to-absolute-glob": "2.0.2", "unique-stream": "2.2.1" - }, - "dependencies": { - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - } - } - }, - "gulp-sourcemaps": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", - "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", - "dev": true, - "requires": { - "convert-source-map": "1.5.0", - "graceful-fs": "4.1.11", - "strip-bom": "2.0.0", - "through2": "2.0.3", - "vinyl": "1.2.0" } }, "is-extglob": { @@ -3622,43 +4949,46 @@ "is-extglob": "2.1.1" } }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "kind-of": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", "dev": true }, "ordered-read-streams": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", - "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", "dev": true, "requires": { - "is-stream": "1.1.0", "readable-stream": "2.3.3" } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", "dev": true, "requires": { - "is-utf8": "0.2.1" + "ansi-cyan": "0.1.1", + "ansi-red": "0.1.1", + "arr-diff": "1.1.0", + "arr-union": "2.1.0", + "extend-shallow": "1.1.4" } }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "unique-stream": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", @@ -3670,39 +5000,42 @@ } }, "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", + "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", "dev": true, "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" + "clone": "2.1.2", + "clone-buffer": "1.0.0", + "clone-stats": "1.0.0", + "cloneable-readable": "1.1.2", + "remove-trailing-separator": "1.1.0", + "replace-ext": "1.0.0" } }, "vinyl-fs": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", - "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.2.tgz", + "integrity": "sha512-AUSFda1OukBwuLPBTbyuO4IRWgfXmqC4UTW0f8xrCa8Hkv9oyIU+NSqBlgfOLZRoUt7cHdo75hKQghCywpIyIw==", "dev": true, "requires": { - "duplexify": "3.5.1", - "glob-stream": "5.3.5", + "fs-mkdirp-stream": "1.0.0", + "glob-stream": "6.1.0", "graceful-fs": "4.1.11", - "gulp-sourcemaps": "1.6.0", - "is-valid-glob": "0.3.0", + "is-valid-glob": "1.0.0", "lazystream": "1.0.0", - "lodash.isequal": "4.5.0", - "merge-stream": "1.0.1", - "mkdirp": "0.5.1", - "object-assign": "4.1.1", + "lead": "1.0.0", + "object.assign": "4.1.0", + "pumpify": "1.4.0", "readable-stream": "2.3.3", - "strip-bom": "2.0.0", - "strip-bom-stream": "1.0.0", + "remove-bom-buffer": "3.0.0", + "remove-bom-stream": "1.2.0", + "resolve-options": "1.1.0", "through2": "2.0.3", - "through2-filter": "2.0.0", - "vali-date": "1.0.0", - "vinyl": "1.2.0" + "to-through": "2.0.0", + "value-or-function": "3.0.0", + "vinyl": "2.1.0", + "vinyl-sourcemap": "1.1.0" } } } @@ -3828,6 +5161,12 @@ "sparkles": "1.0.0" } }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -3981,6 +5320,15 @@ "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", "dev": true }, + "ignore-walk": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", + "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", + "optional": true, + "requires": { + "minimatch": "3.0.4" + } + }, "import-lazy": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", @@ -3993,15 +5341,6 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, - "requires": { - "repeating": "2.0.1" - } - }, "indexof": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", @@ -4066,15 +5405,25 @@ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, "ip-regex": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-1.0.3.tgz", - "integrity": "sha1-3FiQdvZZ9BnCIgOaMzFvHHOH7/0=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", "dev": true }, "ipaddr.js": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.5.2.tgz", - "integrity": "sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A=" + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", + "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=" + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "requires": { + "is-relative": "1.0.0", + "is-windows": "1.0.2" + } }, "is-accessor-descriptor": { "version": "1.0.0", @@ -4221,14 +5570,20 @@ } }, "is-ip": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-ip/-/is-ip-1.0.0.tgz", - "integrity": "sha1-K7aVn3l8zW+f3IEnWLy8h8TFkHQ=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ip/-/is-ip-2.0.0.tgz", + "integrity": "sha1-aO6gfooKCpTC0IDdZ0xzGrKkYas=", "dev": true, "requires": { - "ip-regex": "1.0.3" + "ip-regex": "2.1.0" } }, + "is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", + "dev": true + }, "is-npm": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", @@ -4316,6 +5671,15 @@ "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", "dev": true }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "requires": { + "is-unc-path": "1.0.0" + } + }, "is-retry-allowed": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", @@ -4333,15 +5697,30 @@ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "requires": { + "unc-path-regex": "0.1.2" + } + }, "is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" }, "is-valid-glob": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", - "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, "isarray": { @@ -4349,11 +5728,6 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, - "isemail": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz", - "integrity": "sha1-vgPfjMPineTSxd9lASY/H6RZXpo=" - }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -4467,24 +5841,6 @@ "resolved": "https://registry.npmjs.org/jju/-/jju-1.3.0.tgz", "integrity": "sha1-2t2e8BkkvHKLA/L3l5vb1i96Kqo=" }, - "joi": { - "version": "6.10.1", - "resolved": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz", - "integrity": "sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY=", - "requires": { - "hoek": "2.16.3", - "isemail": "1.2.0", - "moment": "2.20.1", - "topo": "1.1.0" - }, - "dependencies": { - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" - } - } - }, "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", @@ -4543,12 +5899,6 @@ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, - "json3": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", - "dev": true - }, "json5": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", @@ -4569,9 +5919,9 @@ "dev": true }, "jsonwebtoken": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.1.0.tgz", - "integrity": "sha1-xjl80uX9WD1lwAeoPce7eOaYK4M=", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.2.1.tgz", + "integrity": "sha512-l8rUBr0fqYYwPc8/ZGrue7GiW7vWdZtZqelxo4Sd5lMvuEeCK8/wS54sEo6tJhdZ6hqfutsj6COgC0d1XdbHGw==", "requires": { "jws": "3.1.4", "lodash.includes": "4.3.0", @@ -4581,8 +5931,15 @@ "lodash.isplainobject": "4.0.6", "lodash.isstring": "4.0.1", "lodash.once": "4.1.1", - "ms": "2.0.0", + "ms": "2.1.1", "xtend": "4.0.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==" + } } }, "jsprim": { @@ -4618,9 +5975,9 @@ } }, "kareem": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/kareem/-/kareem-1.5.0.tgz", - "integrity": "sha1-4+QQHZ3P3imXadr0tNtk2JXRdEg=" + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.0.7.tgz", + "integrity": "sha512-p8+lEpsNs4N0fvNOC1/zzDO0wDrD3Pb1G+OwfIG+gKVK3MyY5jeaGYh+9Qx6jb4fEG2b3E6U98vaE9MH7Gilsw==" }, "kind-of": { "version": "3.2.2", @@ -4679,6 +6036,15 @@ "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", "dev": true }, + "lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", + "dev": true, + "requires": { + "flush-write-stream": "1.0.3" + } + }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -4949,7 +6315,7 @@ "integrity": "sha1-2UpGSPmxwXnWT6lykSaL22zpQ08=", "dev": true, "requires": { - "uc.micro": "1.0.3" + "uc.micro": "1.0.5" } }, "load-json-file": { @@ -4969,28 +6335,12 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" }, - "lodash._baseassign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", - "dev": true, - "requires": { - "lodash._basecopy": "3.0.1", - "lodash.keys": "3.1.2" - } - }, "lodash._basecopy": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", "dev": true }, - "lodash._basecreate": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", - "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", - "dev": true - }, "lodash._basetostring": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", @@ -5044,17 +6394,6 @@ "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" }, - "lodash.create": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", - "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", - "dev": true, - "requires": { - "lodash._baseassign": "3.2.0", - "lodash._basecreate": "3.0.3", - "lodash._isiterateecall": "3.0.9" - } - }, "lodash.escape": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", @@ -5091,12 +6430,6 @@ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", - "dev": true - }, "lodash.isinteger": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", @@ -5167,9 +6500,9 @@ } }, "log-driver": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", - "integrity": "sha1-euTsJXMC/XkNVXyxDJcQDYV7AFY=", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", + "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", "dev": true }, "longest": { @@ -5186,16 +6519,6 @@ "js-tokens": "3.0.2" } }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, - "requires": { - "currently-unhandled": "0.4.1", - "signal-exit": "3.0.2" - } - }, "lowdb": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/lowdb/-/lowdb-0.14.0.tgz", @@ -5226,14 +6549,9 @@ "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", "dev": true, "requires": { - "es5-ext": "0.10.37" + "es5-ext": "0.10.41" } }, - "lsmod": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lsmod/-/lsmod-1.0.0.tgz", - "integrity": "sha1-mgD3bco26yP6BTUK/htYXUKZ5ks=" - }, "make-dir": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.1.0.tgz", @@ -5266,12 +6584,6 @@ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - }, "map-stream": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", @@ -5288,16 +6600,16 @@ } }, "markdown-it": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.0.tgz", - "integrity": "sha512-tNuOCCfunY5v5uhcO2AUMArvKAyKMygX8tfup/JrgnsDqcCATQsAExBq7o5Ml9iMmO82bk6jYNLj6khcrl0JGA==", + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.1.tgz", + "integrity": "sha512-CzzqSSNkFRUf9vlWvhK1awpJreMRqdCrBvZ8DIoDWTOkESMIF741UPAhuAmbyWmdiFPA6WARNhnu2M6Nrhwa+A==", "dev": true, "requires": { "argparse": "1.0.9", "entities": "1.1.1", "linkify-it": "2.0.3", "mdurl": "1.0.1", - "uc.micro": "1.0.3" + "uc.micro": "1.0.5" } }, "marked": { @@ -5305,6 +6617,16 @@ "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.9.tgz", "integrity": "sha512-nW5u0dxpXxHfkHzzrveY45gCbi+R4PaO4WRZYqZNl+vB0hVGeqlFn0aOg1c8AKL63TrNFn9Bm2UP4AdiZ9TPLw==" }, + "md5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", + "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", + "requires": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "1.1.6" + } + }, "mdurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", @@ -5317,45 +6639,19 @@ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, "memoizee": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.11.tgz", - "integrity": "sha1-vemBdmPJ5A/bKk6hw2cpYIeujI8=", + "version": "0.4.12", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.12.tgz", + "integrity": "sha512-sprBu6nwxBWBvBOh5v2jcsGqiGLlL2xr2dLub3vR8dnE8YB17omwtm/0NSHl8jjNbcsJd5GMWJAnTSVe/O0Wfg==", "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.37", + "es5-ext": "0.10.41", "es6-weak-map": "2.0.2", "event-emitter": "0.3.5", "is-promise": "2.1.0", "lru-queue": "0.1.0", "next-tick": "1.0.0", - "timers-ext": "0.1.2" - } - }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dev": true, - "requires": { - "camelcase-keys": "2.1.0", - "decamelize": "1.2.0", - "loud-rejection": "1.6.0", - "map-obj": "1.0.1", - "minimist": "1.2.0", - "normalize-package-data": "2.4.0", - "object-assign": "4.1.1", - "read-pkg-up": "1.0.1", - "redent": "1.0.0", - "trim-newlines": "1.0.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } + "timers-ext": "0.1.5" } }, "merge-descriptors": { @@ -5363,15 +6659,6 @@ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" }, - "merge-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", - "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true, - "requires": { - "readable-stream": "2.3.3" - } - }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -5412,14 +6699,98 @@ "colors": "1.1.2", "inquirer": "0.12.0", "mkdirp": "0.5.1", - "mongoose": "4.13.9", + "mongoose": "4.13.12", "yargs": "4.8.1" }, "dependencies": { + "async": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.1.4.tgz", + "integrity": "sha1-LSFgx3iAMuTdbL4lAvH5osj2zeQ=", + "requires": { + "lodash": "4.17.4" + } + }, "colors": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=" + }, + "kareem": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-1.5.0.tgz", + "integrity": "sha1-4+QQHZ3P3imXadr0tNtk2JXRdEg=" + }, + "mongodb": { + "version": "2.2.34", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.34.tgz", + "integrity": "sha1-o09Zu+thdUrsQy3nLD/iFSakTBo=", + "requires": { + "es6-promise": "3.2.1", + "mongodb-core": "2.1.18", + "readable-stream": "2.2.7" + } + }, + "mongodb-core": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.18.tgz", + "integrity": "sha1-TEYTm986HwMt7ZHbSfOO7AFlkFA=", + "requires": { + "bson": "1.0.6", + "require_optional": "1.0.1" + } + }, + "mongoose": { + "version": "4.13.12", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-4.13.12.tgz", + "integrity": "sha512-pH8NK5AYGbnPeEFFGs5ACk18vzzcy4DFT48U9kKvkfg6SI3nJZkzGfN7o1NDWjy+kP26hWyU/AMhYTfe5hSVnA==", + "requires": { + "async": "2.1.4", + "bson": "1.0.6", + "hooks-fixed": "2.0.2", + "kareem": "1.5.0", + "lodash.get": "4.4.2", + "mongodb": "2.2.34", + "mpath": "0.3.0", + "mpromise": "0.5.5", + "mquery": "2.3.3", + "ms": "2.0.0", + "muri": "1.3.0", + "regexp-clone": "0.0.1", + "sliced": "1.0.1" + } + }, + "mquery": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-2.3.3.tgz", + "integrity": "sha512-NC8L14kn+qxJbbJ1gbcEMDxF0sC3sv+1cbRReXXwVvowcwY1y9KoVZFq0ebwARibsadu8lx8nWGvm3V0Pf0ZWQ==", + "requires": { + "bluebird": "3.5.0", + "debug": "2.6.9", + "regexp-clone": "0.0.1", + "sliced": "0.0.5" + }, + "dependencies": { + "sliced": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/sliced/-/sliced-0.0.5.tgz", + "integrity": "sha1-XtwETKTrb3gW1Qui/GPiXY/kcH8=" + } + } + }, + "readable-stream": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", + "integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=", + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } } } }, @@ -5441,6 +6812,11 @@ "mime-db": "1.30.0" } }, + "mimic-response": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.0.tgz", + "integrity": "sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4=" + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -5454,6 +6830,30 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, + "minipass": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.4.tgz", + "integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==", + "requires": { + "safe-buffer": "5.1.1", + "yallist": "3.0.2" + }, + "dependencies": { + "yallist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", + "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=" + } + } + }, + "minizlib": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.1.0.tgz", + "integrity": "sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==", + "requires": { + "minipass": "2.2.4" + } + }, "mixin-deep": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.0.tgz", @@ -5484,55 +6884,45 @@ } }, "mocha": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", - "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", + "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", "dev": true, "requires": { "browser-stdout": "1.3.0", - "commander": "2.9.0", - "debug": "2.6.8", - "diff": "3.2.0", + "commander": "2.11.0", + "debug": "3.1.0", + "diff": "3.3.1", "escape-string-regexp": "1.0.5", - "glob": "7.1.1", - "growl": "1.9.2", + "glob": "7.1.2", + "growl": "1.10.3", "he": "1.1.1", - "json3": "3.3.2", - "lodash.create": "3.1.1", "mkdirp": "0.5.1", - "supports-color": "3.1.2" + "supports-color": "4.4.0" }, "dependencies": { "debug": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" } }, - "glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", - "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true }, "supports-color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", - "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "2.0.0" } } } @@ -5544,61 +6934,41 @@ "dev": true }, "moment": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz", - "integrity": "sha512-Yh9y73JRljxW5QxN08Fner68eFLxM5ynNOAw2LbIB1YAGeQzZT8QFSUvkAz609Zf+IHhhaUxqZK8dG3W/+HEvg==" + "version": "2.22.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.1.tgz", + "integrity": "sha512-shJkRTSebXvsVqk56I+lkb2latjBs8I+pc2TzWc545y2iFnSjm7Wg0QMh+ZWcdSLQyGEau5jI8ocnmkyTgr9YQ==" }, "mongodb": { - "version": "2.2.34", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.34.tgz", - "integrity": "sha1-o09Zu+thdUrsQy3nLD/iFSakTBo=", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.0.7.tgz", + "integrity": "sha512-n/14kMJEoARXz1qhpNPhUocqy+z5130jhqgEIX1Tsl8UVpHrndQ8et+VmgC4yPK/I8Tcgc93JEMQCHTekBUnNA==", "requires": { - "es6-promise": "3.2.1", - "mongodb-core": "2.1.18", - "readable-stream": "2.2.7" - }, - "dependencies": { - "readable-stream": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", - "integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=", - "requires": { - "buffer-shims": "1.0.0", - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - } + "mongodb-core": "3.0.7" } }, "mongodb-core": { - "version": "2.1.18", - "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.18.tgz", - "integrity": "sha1-TEYTm986HwMt7ZHbSfOO7AFlkFA=", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-3.0.7.tgz", + "integrity": "sha512-z6YufO7s40wLiv2ssFshqoLS4+Kf+huhHq6KZ7gDArsKNzXYjAwTMnhEIJ9GQ8fIfBGs5tBLNPfbIDoCKGPmOw==", "requires": { - "bson": "1.0.4", + "bson": "1.0.6", "require_optional": "1.0.1" } }, "mongoose": { - "version": "4.13.9", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-4.13.9.tgz", - "integrity": "sha512-UGkSJR5iYHfHGlAyNNJS/mX5HoukDssQoy2pyJTpdyOXnxSw1ujYvMlxEuiIOQEWH2oZSAmHfjH+/igxG1MXLQ==", + "version": "5.0.17", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.0.17.tgz", + "integrity": "sha512-RV1WBQhzW7oOhStR+s7LQYfgQWTJm4hgmU3TqtgTiBCfnj5/sNliX2/SY+ef7tpIZRUqEBV5xITZdAlwQ6Ymdg==", "requires": { "async": "2.1.4", - "bson": "1.0.4", - "hooks-fixed": "2.0.2", - "kareem": "1.5.0", + "bson": "1.0.6", + "kareem": "2.0.7", "lodash.get": "4.4.2", - "mongodb": "2.2.34", - "mpath": "0.3.0", - "mpromise": "0.5.5", - "mquery": "2.3.3", + "mongodb": "3.0.7", + "mongoose-legacy-pluralize": "1.0.2", + "mpath": "0.4.1", + "mquery": "3.0.0", "ms": "2.0.0", - "muri": "1.3.0", "regexp-clone": "0.0.1", "sliced": "1.0.1" }, @@ -5610,9 +6980,19 @@ "requires": { "lodash": "4.17.4" } + }, + "mpath": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.4.1.tgz", + "integrity": "sha512-NNY/MpBkALb9jJmjpBlIi6GRoLveLUM0pJzgbp9vY9F7IQEb/HREC/nxrixechcQwd1NevOhJnWWV8QQQRE+OA==" } } }, + "mongoose-legacy-pluralize": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", + "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==" + }, "morgan": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.0.tgz", @@ -5636,9 +7016,9 @@ "integrity": "sha1-9bJCWddjrMIlewoMjG2Gb9UXMuY=" }, "mquery": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/mquery/-/mquery-2.3.3.tgz", - "integrity": "sha512-NC8L14kn+qxJbbJ1gbcEMDxF0sC3sv+1cbRReXXwVvowcwY1y9KoVZFq0ebwARibsadu8lx8nWGvm3V0Pf0ZWQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.0.0.tgz", + "integrity": "sha512-WL1Lk8v4l8VFSSwN3yCzY9TXw+fKVYKn6f+w86TRzOLSE8k1yTgGaLBPUByJQi8VcLbOdnUneFV/y3Kv874pnQ==", "requires": { "bluebird": "3.5.0", "debug": "2.6.9", @@ -5700,9 +7080,9 @@ "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=" }, "nan": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.6.2.tgz", - "integrity": "sha1-5P805slf37WuzAjeZZb0NgWn20U=" + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" }, "nanomatch": { "version": "1.2.7", @@ -5749,6 +7129,17 @@ "integrity": "sha512-8eRaxn8u/4wN8tGkhlc2cgwwvOLMLUMUn4IYTexMgWd+LyUDfeXVkk2ygQR0hvIHbJQXgHujia3ieUUDwNGkEA==", "dev": true }, + "needle": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.0.tgz", + "integrity": "sha512-eFagy6c+TYayorXw/qtAdSvaUpEbBsDwDyxYFgLZ0lTojfH7K+OdBqAF7TAFwDokJaGpubpSGG0wO3iC0XPi8w==", + "optional": true, + "requires": { + "debug": "2.6.9", + "iconv-lite": "0.4.19", + "sax": "1.2.4" + } + }, "negotiator": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", @@ -5760,6 +7151,14 @@ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, + "node-abi": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.4.1.tgz", + "integrity": "sha512-pUlswqpHQ7zGPI9lGjZ4XDNIEUDbHxsltfIRb7dTnYdhgHWHOcB0MLZKLoCz6UMcGzSPG5wGl1HODZVQAUsH6w==", + "requires": { + "semver": "5.4.1" + } + }, "node-file-cache": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/node-file-cache/-/node-file-cache-1.0.2.tgz", @@ -5785,9 +7184,9 @@ } }, "nodemailer": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-4.4.1.tgz", - "integrity": "sha512-1bnszJJXatcHJhLpxQ1XMkLDjCjPKvGKMtRQ73FOsoNln3UQjddEQmz6fAwM3aj0GtQ3dQX9qtMHPelz63GU7A==" + "version": "4.6.4", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-4.6.4.tgz", + "integrity": "sha512-SD4uuX7NMzZ5f5m1XHDd13J4UC3SmdJk8DsmU1g6Nrs5h3x9LcXr6EBPZIqXRJ3LrF7RdklzGhZRF/TuylTcLg==" }, "nodemailer-markdown": { "version": "1.0.2", @@ -5848,13 +7247,18 @@ } } }, + "noop-logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", + "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=" + }, "nopt": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "requires": { "abbrev": "1.1.1", - "osenv": "0.1.4" + "osenv": "0.1.5" } }, "normalize-package-data": { @@ -5876,6 +7280,31 @@ "remove-trailing-separator": "1.1.0" } }, + "now-and-later": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.0.tgz", + "integrity": "sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4=", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, + "npm-bundled": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.3.tgz", + "integrity": "sha512-ByQ3oJ/5ETLyglU2+8dBObvhfWXX8dtPZDMePCahptliFX2iIuhyEszyFk401PZUNQH20vvdW5MLjJxkwU80Ow==", + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.1.10.tgz", + "integrity": "sha512-AQC0Dyhzn4EiYEfIUjCdMl0JJ61I2ER9ukf/sLxJUcZHfo+VyEfz2rMJgLZSS1v30OxPQe1cN0LZA1xbcaVfWA==", + "optional": true, + "requires": { + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.3" + } + }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -5980,6 +7409,12 @@ "is-extended": "0.0.10" } }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", + "dev": true + }, "object-visit": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", @@ -5997,6 +7432,18 @@ } } }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "function-bind": "1.1.1", + "has-symbols": "1.0.0", + "object-keys": "1.0.11" + } + }, "object.defaults": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", @@ -6187,9 +7634,9 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, "osenv": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", - "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "requires": { "os-homedir": "1.0.2", "os-tmpdir": "1.0.2" @@ -6316,26 +7763,12 @@ } }, "passport-jwt": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-3.0.1.tgz", - "integrity": "sha1-5Pcnba2L0lHUPG/DiIMTC5YycvY=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.0.tgz", + "integrity": "sha512-BwC0n2GP/1hMVjR4QpnvqA61TxenUMlmfNjYNgK0ZAs0HK4SOQkHcSv4L328blNTLtHq7DbmvyNJiH+bn6C5Mg==", "requires": { - "jsonwebtoken": "7.4.3", + "jsonwebtoken": "8.2.1", "passport-strategy": "1.0.0" - }, - "dependencies": { - "jsonwebtoken": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.4.3.tgz", - "integrity": "sha1-d/UCHeBYtgWheD+hKD6ZgS5kVjg=", - "requires": { - "joi": "6.10.1", - "jws": "3.1.4", - "lodash.once": "4.1.1", - "ms": "2.0.0", - "xtend": "4.0.1" - } - } } }, "passport-local": { @@ -6470,12 +7903,80 @@ "pinkie": "2.0.4" } }, + "plugin-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "dev": true, + "requires": { + "ansi-colors": "1.1.0", + "arr-diff": "4.0.0", + "arr-union": "3.1.0", + "extend-shallow": "3.0.2" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", "dev": true }, + "prebuild-install": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-2.5.3.tgz", + "integrity": "sha512-/rI36cN2g7vDQnKWN8Uzupi++KjyqS9iS+/fpwG4Ea8d0Pip0PQ5bshUNzVwt+/D2MRfhVAplYMMvWLqWrCF/g==", + "requires": { + "detect-libc": "1.0.3", + "expand-template": "1.1.0", + "github-from-package": "0.0.0", + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "node-abi": "2.4.1", + "noop-logger": "0.1.1", + "npmlog": "4.1.2", + "os-homedir": "1.0.2", + "pump": "2.0.1", + "rc": "1.2.2", + "simple-get": "2.8.1", + "tar-fs": "1.16.2", + "tunnel-agent": "0.6.0", + "which-pm-runs": "1.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -6516,12 +8017,12 @@ "dev": true }, "proxy-addr": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.2.tgz", - "integrity": "sha1-ZXFQT0e7mI7IGAJT+F3X4UlSvew=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", + "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==", "requires": { "forwarded": "0.1.2", - "ipaddr.js": "1.5.2" + "ipaddr.js": "1.6.0" } }, "ps-tree": { @@ -6548,6 +8049,40 @@ "ps-tree": "1.1.0" } }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "1.4.0", + "once": "1.4.0" + } + }, + "pumpify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.4.0.tgz", + "integrity": "sha512-2kmNR9ry+Pf45opRVirpNuIFotsxUGLaYqxIwuR77AYrYRMuFCz9eryHBS52L360O+NcR383CL4QYlMKPq4zYA==", + "dev": true, + "requires": { + "duplexify": "3.5.4", + "inherits": "2.0.3", + "pump": "2.0.1" + }, + "dependencies": { + "duplexify": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.4.tgz", + "integrity": "sha512-JzYSLYMhoVVBe8+mbHQ4KgpvHpm0DZpJuL8PY93Vyv1fW7jYJ90LoXa1di/CVbJM+TgMs91rbDapE/RNIfnJsA==", + "dev": true, + "requires": { + "end-of-stream": "1.4.0", + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "stream-shift": "1.0.0" + } + } + } + }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", @@ -6601,17 +8136,22 @@ "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" }, "raven": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/raven/-/raven-2.3.0.tgz", - "integrity": "sha1-lvFTRr2qQzs7bUcTCARQYVWDPWk=", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/raven/-/raven-2.6.0.tgz", + "integrity": "sha1-OAaoLJ7ozT51w7fqe7GTWq0JLQw=", "requires": { "cookie": "0.3.1", - "lsmod": "1.0.0", - "stack-trace": "0.0.9", + "md5": "2.2.1", + "stack-trace": "0.0.10", "timed-out": "4.0.1", "uuid": "3.0.0" }, "dependencies": { + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + }, "uuid": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.0.tgz", @@ -6742,20 +8282,10 @@ "resolve": "1.5.0" } }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, - "requires": { - "indent-string": "2.1.0", - "strip-indent": "1.0.1" - } - }, "reflect-metadata": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.10.tgz", - "integrity": "sha1-tPg3BEFqytiZiMmxVjXUfgO5NEo=" + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.12.tgz", + "integrity": "sha512-n+IyV+nGz3+0q3/Yf1ra12KpCyi001bi4XFxSjbiWWjfqb52iTTtpGXmCCAOWWIAn9KEuFZKGqBERHmrtScZ3A==" }, "regenerate": { "version": "1.3.3", @@ -6849,67 +8379,69 @@ } }, "remap-istanbul": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/remap-istanbul/-/remap-istanbul-0.9.5.tgz", - "integrity": "sha1-oYYXsfMe7Fp9vud1OCmLd1YGqqg=", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/remap-istanbul/-/remap-istanbul-0.11.0.tgz", + "integrity": "sha512-gQqJ+mW+jF7Hv8hXYO/pIRMz6WgZyrlp3rSxejGXzwqtK9+sNTB/tUSnLWAFTgQx4x5dx0sPDsLvbpZXuZ0omQ==", "dev": true, "requires": { "amdefine": "1.0.1", - "gulp-util": "3.0.7", "istanbul": "0.4.5", "minimatch": "3.0.4", - "source-map": "0.5.7", + "plugin-error": "0.1.2", + "source-map": "0.6.1", "through2": "2.0.1" }, "dependencies": { - "dateformat": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", - "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", - "dev": true, - "requires": { - "get-stdin": "4.0.1", - "meow": "3.7.0" - } - }, - "gulp-util": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.7.tgz", - "integrity": "sha1-eJJcS4+LSQBawBoBHFV+YhiUHLs=", - "dev": true, - "requires": { - "array-differ": "1.0.0", - "array-uniq": "1.0.3", - "beeper": "1.1.1", - "chalk": "1.1.3", - "dateformat": "1.0.12", - "fancy-log": "1.3.0", - "gulplog": "1.0.0", - "has-gulplog": "0.1.0", - "lodash._reescape": "3.0.0", - "lodash._reevaluate": "3.0.0", - "lodash._reinterpolate": "3.0.0", - "lodash.template": "3.6.2", - "minimist": "1.2.0", - "multipipe": "0.1.2", - "object-assign": "3.0.0", - "replace-ext": "0.0.1", - "through2": "2.0.1", - "vinyl": "0.5.3" + "arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-slice": "0.2.3" } }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", "dev": true }, - "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", + "dev": true, + "requires": { + "kind-of": "1.1.0" + } + }, + "kind-of": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", "dev": true }, + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", + "dev": true, + "requires": { + "ansi-cyan": "0.1.1", + "ansi-red": "0.1.1", + "arr-diff": "1.1.0", + "arr-union": "2.1.0", + "extend-shallow": "1.1.4" + } + }, "readable-stream": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", @@ -6924,6 +8456,12 @@ "util-deprecate": "1.0.2" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", @@ -6942,6 +8480,27 @@ } } }, + "remove-bom-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "dev": true, + "requires": { + "is-buffer": "1.1.6", + "is-utf8": "0.2.1" + } + }, + "remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", + "dev": true, + "requires": { + "remove-bom-buffer": "3.0.0", + "safe-buffer": "5.1.1", + "through2": "2.0.3" + } + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -7084,6 +8643,15 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" }, + "resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", + "dev": true, + "requires": { + "value-or-function": "3.0.0" + } + }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -7118,15 +8686,15 @@ } }, "routing-controllers": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/routing-controllers/-/routing-controllers-0.7.6.tgz", - "integrity": "sha512-JiZpGt+z8mJYT2X4Vl0DghJAJWSPT5d4vX3keRf1ma2XTmpOKBsBQuEjTluanIDG+RfvZ1qecGfH4NQj1GfM2g==", + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/routing-controllers/-/routing-controllers-0.7.7.tgz", + "integrity": "sha512-Z2173DC3dqDvnTxwFPx9mToX5DZ0MsgMae7ENwuK45dbJPK3D8vdZAzSgTcFR+CtrzfDR66Y8E5I3CYkPJWVWg==", "requires": { - "class-transformer": "0.1.8", - "class-validator": "0.7.3", + "class-transformer": "0.1.9", + "class-validator": "0.8.4", "cookie": "0.3.1", "glob": "7.1.2", - "reflect-metadata": "0.1.10", + "reflect-metadata": "0.1.12", "template-url": "1.0.0" } }, @@ -7139,13 +8707,77 @@ } }, "run-sequence": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/run-sequence/-/run-sequence-2.2.0.tgz", - "integrity": "sha512-xW5DmUwdvoyYQUMPKN8UW7TZSFs7AxtT59xo1m5y91jHbvwGlGgOmdV1Yw5P68fkjf3aHUZ4G1o1mZCtNe0qtw==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/run-sequence/-/run-sequence-2.2.1.tgz", + "integrity": "sha512-qkzZnQWMZjcKbh3CNly2srtrkaO/2H/SI5f2eliMCapdRD3UhMrwjfOAZJAnZ2H8Ju4aBzFZkBGXUqFs9V0yxw==", "dev": true, "requires": { "chalk": "1.1.3", - "gulp-util": "3.0.8" + "fancy-log": "1.3.2", + "plugin-error": "0.1.2" + }, + "dependencies": { + "arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-slice": "0.2.3" + } + }, + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", + "dev": true + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", + "dev": true, + "requires": { + "kind-of": "1.1.0" + } + }, + "fancy-log": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", + "dev": true, + "requires": { + "ansi-gray": "0.1.1", + "color-support": "1.1.3", + "time-stamp": "1.1.0" + } + }, + "kind-of": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", + "dev": true + }, + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", + "dev": true, + "requires": { + "ansi-cyan": "0.1.1", + "ansi-red": "0.1.1", + "arr-diff": "1.1.0", + "arr-union": "2.1.0", + "extend-shallow": "1.1.4" + } + } } }, "rx-lite": { @@ -7158,6 +8790,12 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "optional": true + }, "semver": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", @@ -7173,14 +8811,14 @@ } }, "send": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz", - "integrity": "sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A==", + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", "requires": { "debug": "2.6.9", - "depd": "1.1.1", + "depd": "1.1.2", "destroy": "1.0.4", - "encodeurl": "1.0.1", + "encodeurl": "1.0.2", "escape-html": "1.0.3", "etag": "1.8.1", "fresh": "0.5.2", @@ -7189,13 +8827,13 @@ "ms": "2.0.0", "on-finished": "2.3.0", "range-parser": "1.2.0", - "statuses": "1.3.1" + "statuses": "1.4.0" }, "dependencies": { - "statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" } } }, @@ -7206,14 +8844,14 @@ "dev": true }, "serve-static": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz", - "integrity": "sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", "requires": { - "encodeurl": "1.0.1", + "encodeurl": "1.0.2", "escape-html": "1.0.3", "parseurl": "1.3.2", - "send": "0.16.1" + "send": "0.16.2" } }, "set-blocking": { @@ -7252,6 +8890,54 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" }, + "sharp": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.20.2.tgz", + "integrity": "sha512-cFL2qUT9eyR29bI+gj5kQjWlj+VIuTGdcY/CErQqmwJ4FKTXhmdE6d/zwjmrAokzr5n547KQed8HFQsmyUv9uw==", + "requires": { + "color": "3.0.0", + "detect-libc": "1.0.3", + "fs-copy-file-sync": "1.1.0", + "nan": "2.10.0", + "npmlog": "4.1.2", + "prebuild-install": "2.5.3", + "semver": "5.5.0", + "simple-get": "2.8.1", + "tar": "4.4.2", + "tunnel-agent": "0.6.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + }, + "tar": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.2.tgz", + "integrity": "sha512-BfkE9CciGGgDsATqkikUHrQrraBCO+ke/1f6SFAEMnxyyfN9lxC+nW1NFWMpqH865DhHIy9vQi682gk1X7friw==", + "requires": { + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.2.4", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.2", + "yallist": "3.0.2" + } + }, + "yallist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", + "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=" + } + } + }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -7268,9 +8954,9 @@ "dev": true }, "shelljs": { - "version": "0.7.8", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", - "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.1.tgz", + "integrity": "sha512-YA/iYtZpzFe5HyWVGrb02FjPxc4EMCfpoU/Phg9fQoyMC72u9598OUBrsU8IrtwAKG0tO8IYaqbaLIw+k3IRGA==", "dev": true, "requires": { "glob": "7.1.2", @@ -7289,6 +8975,36 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, + "simple-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", + "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" + }, + "simple-get": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", + "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", + "requires": { + "decompress-response": "3.3.0", + "once": "1.4.0", + "simple-concat": "1.0.0" + } + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "requires": { + "is-arrayish": "0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.1.tgz", + "integrity": "sha1-wt/DhquqDD4zxI2z/ocFnmkGXv0=" + } + } + }, "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", @@ -7764,16 +9480,6 @@ "is-utf8": "0.2.1" } }, - "strip-bom-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz", - "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", - "dev": true, - "requires": { - "first-chunk-stream": "1.0.0", - "strip-bom": "2.0.0" - } - }, "strip-bom-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", @@ -7786,53 +9492,36 @@ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, - "requires": { - "get-stdin": "4.0.1" - } - }, "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=" }, "superagent": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-2.3.0.tgz", - "integrity": "sha1-cDUpoHFOV+EjlZ3e+84ZOy5Q0RU=", + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.2.tgz", + "integrity": "sha512-gVH4QfYHcY3P0f/BZzavLreHW3T1v7hG9B+hpMQotGQqurOvhv87GcMCd6LWySmBuf+BDR44TQd0aISjVHLeNQ==", "dev": true, "requires": { "component-emitter": "1.2.1", - "cookiejar": "2.0.6", - "debug": "2.6.9", + "cookiejar": "2.1.1", + "debug": "3.1.0", "extend": "3.0.1", - "form-data": "1.0.0-rc4", - "formidable": "1.1.1", + "form-data": "2.3.1", + "formidable": "1.2.1", "methods": "1.1.2", "mime": "1.4.1", "qs": "6.5.1", "readable-stream": "2.3.3" }, "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "form-data": { - "version": "1.0.0-rc4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc4.tgz", - "integrity": "sha1-BaxrwiIntD5EYfSIFhVUaZ1Pi14=", + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { - "async": "1.5.2", - "combined-stream": "1.0.5", - "mime-types": "2.1.17" + "ms": "2.0.0" } } } @@ -7852,6 +9541,28 @@ "inherits": "2.0.3" } }, + "tar-fs": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.2.tgz", + "integrity": "sha512-LdknWjPEiZC1nOBwhv0JBzfJBGPJar08dZg2rwZe0ZTLQoRGEzgrl7vF3qUEkCHpI/wN9e7RyCuDhMsJUCLPPQ==", + "requires": { + "chownr": "1.0.1", + "mkdirp": "0.5.1", + "pump": "1.0.3", + "tar-stream": "1.5.5" + }, + "dependencies": { + "pump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", + "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "requires": { + "end-of-stream": "1.4.0", + "once": "1.4.0" + } + } + } + }, "tar-pack": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.1.tgz", @@ -7872,7 +9583,7 @@ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.5.tgz", "integrity": "sha512-mQdgLPc/Vjfr3VWqWbfxW8yQNiJCbAZ+Gf6GDu1Cy0bdb33ofyiNGBtAY96jHFhDuivCwgW1H9DgTON+INiXgg==", "requires": { - "bl": "1.2.1", + "bl": "1.2.2", "end-of-stream": "1.4.0", "readable-stream": "2.3.3", "xtend": "4.0.1" @@ -7972,22 +9683,23 @@ "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" }, "timers-ext": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.2.tgz", - "integrity": "sha1-YcxHp2wavTGV8UUn+XjViulMUgQ=", + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.5.tgz", + "integrity": "sha512-tsEStd7kmACHENhsUPaxb8Jf8/+GZZxyNFQbZD07HQOyooOa6At1rQqjffgvg7n+dxscQa9cjjMdWhJtsP2sxg==", "dev": true, "requires": { - "es5-ext": "0.10.37", + "es5-ext": "0.10.41", "next-tick": "1.0.0" } }, "to-absolute-glob": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", - "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", "dev": true, "requires": { - "extend-shallow": "2.0.1" + "is-absolute": "1.0.0", + "is-negated-glob": "1.0.0" } }, "to-fast-properties": { @@ -8104,6 +9816,15 @@ } } }, + "to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "dev": true, + "requires": { + "through2": "2.0.3" + } + }, "to-utf-8": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/to-utf-8/-/to-utf-8-1.3.0.tgz", @@ -8123,21 +9844,6 @@ } } }, - "topo": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz", - "integrity": "sha1-6ddRYV0buH3IZdsYL6HKCl71NtU=", - "requires": { - "hoek": "2.16.3" - }, - "dependencies": { - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" - } - } - }, "touch": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", @@ -8166,86 +9872,87 @@ "punycode": "1.4.1" } }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true - }, "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" }, "tslib": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.8.1.tgz", - "integrity": "sha1-aUavLR1lGnsYY7Ux1uWvpBqkTqw=", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz", + "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==", "dev": true }, "tslint": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.8.0.tgz", - "integrity": "sha1-H0mtWy53x2w69N3K5VKuTjYS6xM=", + "version": "5.9.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.9.1.tgz", + "integrity": "sha1-ElX4ej/1frCw4fDmEKi0dIBGya4=", "dev": true, "requires": { "babel-code-frame": "6.26.0", "builtin-modules": "1.1.1", - "chalk": "2.3.0", - "commander": "2.9.0", - "diff": "3.2.0", + "chalk": "2.3.2", + "commander": "2.15.1", + "diff": "3.3.1", "glob": "7.1.2", + "js-yaml": "3.10.0", "minimatch": "3.0.4", "resolve": "1.5.0", "semver": "5.4.1", - "tslib": "1.8.1", - "tsutils": "2.16.0" + "tslib": "1.9.0", + "tsutils": "2.22.2" }, "dependencies": { "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "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==", "dev": true, "requires": { "color-convert": "1.9.1" } }, "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", "dev": true, "requires": { - "ansi-styles": "3.2.0", + "ansi-styles": "3.2.1", "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" + "supports-color": "5.3.0" } }, + "commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", "dev": true, "requires": { - "has-flag": "2.0.0" + "has-flag": "3.0.0" } } } }, "tsutils": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.16.0.tgz", - "integrity": "sha512-9Ier/60O7OZRNPiw+or5QAtAY4kQA+WDiO/r6xOYATEyefH9bdfvTRLCxrYnFhQlZfET2vYXKfpr3Vw2BiArZw==", + "version": "2.22.2", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.22.2.tgz", + "integrity": "sha512-u06FUSulCJ+Y8a2ftuqZN6kIGqdP2yJjUPEngXqmdPND4UQfb04igcotH+dw+IFr417yP6muCLE8/5/Qlfnx0w==", "dev": true, "requires": { - "tslib": "1.8.1" + "tslib": "1.9.0" } }, "tunnel-agent": { @@ -8292,43 +9999,55 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "typedoc": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.9.0.tgz", - "integrity": "sha512-numP0CtcUK4I1Vssw6E1N/FjyJWpWqhLT4Zb7Gw3i7ca3ElnYh6z41Y/tcUhMsMYn6L8b67E/Fu4XYYKkNaLbA==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.11.1.tgz", + "integrity": "sha512-jdNIoHm5wkZqxQTe/g9AQ3LKnZyrzHXqu6A/c9GUOeJyBWLxNr7/Dm3rwFvLksuxRNwTvY/0HRDU9sJTa9WQSg==", "dev": true, "requires": { - "@types/fs-extra": "4.0.0", - "@types/handlebars": "4.0.31", - "@types/highlight.js": "9.1.8", - "@types/lodash": "4.14.74", + "@types/fs-extra": "5.0.1", + "@types/handlebars": "4.0.36", + "@types/highlight.js": "9.12.2", + "@types/lodash": "4.14.104", "@types/marked": "0.3.0", - "@types/minimatch": "2.0.29", - "@types/shelljs": "0.7.0", - "fs-extra": "4.0.3", + "@types/minimatch": "3.0.3", + "@types/shelljs": "0.7.8", + "fs-extra": "5.0.0", "handlebars": "4.0.11", "highlight.js": "9.12.0", - "lodash": "4.17.4", - "marked": "0.3.9", + "lodash": "4.17.5", + "marked": "0.3.18", "minimatch": "3.0.4", "progress": "2.0.0", - "shelljs": "0.7.8", + "shelljs": "0.8.1", "typedoc-default-themes": "0.5.0", - "typescript": "2.4.1" + "typescript": "2.7.2" }, "dependencies": { "@types/fs-extra": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-4.0.0.tgz", - "integrity": "sha512-PlKJw6ujJXLJjbvB3T0UCbY3jibKM6/Ya5cc9j1q+mYDeK3aR4Dp+20ZwxSuvJr9mIoPxp7+IL4aMOEvsscRTA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.1.tgz", + "integrity": "sha512-h3wnflb+jMTipvbbZnClgA2BexrT4w0GcfoCz5qyxd0IRsbqhLSyesM6mqZTAnhbVmhyTm5tuxfRu9R+8l+lGw==", "dev": true, "requires": { "@types/node": "8.0.53" } }, + "lodash": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", + "dev": true + }, + "marked": { + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.18.tgz", + "integrity": "sha512-49i2QYhfULqaXzNZpxC808PisuCTGT2fgG0zrzdCI9N3rIfAWfW0nggvbXr6zvpynZdOG5+9xNxdzP0kwZnERw==", + "dev": true + }, "typescript": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.4.1.tgz", - "integrity": "sha1-w8yxbdqgsjFN4DHn5v7onlujRrw=", + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.7.2.tgz", + "integrity": "sha512-p5TCYZDAO0m4G344hD+wx/LATebLWZNkkh2asWUFqSsD2OrDNhbAHuSjobrmsUmdzjJjEeZVU9g1h3O6vpstnw==", "dev": true } } @@ -8340,15 +10059,15 @@ "dev": true }, "typescript": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.6.2.tgz", - "integrity": "sha1-PFtv1/beCRQmkCfwPAlGdY92c6Q=", + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.8.3.tgz", + "integrity": "sha512-K7g15Bb6Ra4lKf7Iq2l/I5/En+hLIHmxWZGq3D4DIRNFxMNV6j2SHSvDOqs2tGd4UvD/fJvrwopzQXjLrT7Itw==", "dev": true }, "uc.micro": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.3.tgz", - "integrity": "sha1-ftUNXg+an7ClczeSWfKndFjVAZI=", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.5.tgz", + "integrity": "sha512-JoLI4g5zv5qNyT09f4YAvEZIIV1oOjqnewYg5D38dkQljIzpPT296dbIGvKro3digYI1bkb7W6EP1y4uDlmzLg==", "dev": true }, "uglify-js": { @@ -8700,12 +10419,6 @@ "user-home": "1.1.1" } }, - "vali-date": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", - "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", - "dev": true - }, "validate-npm-package-license": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", @@ -8716,9 +10429,15 @@ } }, "validator": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-9.2.0.tgz", - "integrity": "sha512-6Ij4Eo0KM4LkR0d0IegOwluG5453uqT5QyF5SV5Ezvm8/zmkKI/L4eoraafZGlZPC9guLkwKzgypcw8VGWWnGA==" + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/validator/-/validator-9.4.1.tgz", + "integrity": "sha512-YV5KjzvRmSyJ1ee/Dm5UED0G+1L4GZnLN3w6/T+zZm8scVua4sOhYKWTUrKa0H/tMiJyO9QLHMPN+9mB/aMunA==" + }, + "value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", + "dev": true }, "vary": { "version": "1.1.2", @@ -8833,6 +10552,55 @@ } } }, + "vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", + "dev": true, + "requires": { + "append-buffer": "1.0.2", + "convert-source-map": "1.5.0", + "graceful-fs": "4.1.11", + "normalize-path": "2.1.1", + "now-and-later": "2.0.0", + "remove-bom-buffer": "3.0.0", + "vinyl": "2.1.0" + }, + "dependencies": { + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "vinyl": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", + "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", + "dev": true, + "requires": { + "clone": "2.1.2", + "clone-buffer": "1.0.0", + "clone-stats": "1.0.0", + "cloneable-readable": "1.1.2", + "remove-trailing-separator": "1.1.0", + "replace-ext": "1.0.0" + } + } + } + }, "vinyl-sourcemaps-apply": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", @@ -8856,6 +10624,11 @@ "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" }, + "which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=" + }, "wide-align": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", @@ -8879,9 +10652,9 @@ "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=" }, "winston": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.0.tgz", - "integrity": "sha1-gIBQuT1SZh7Z+2wms/DIJnCLCu4=", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.2.tgz", + "integrity": "sha512-4S/Ad4ZfSNl8OccCLxnJmNISWcm2joa6Q0YGDxlxMzH0fgSwWsjMt+SmlNwCqdpaPg3ev1HKkMBsIiXeSUwpbA==", "requires": { "async": "1.0.0", "colors": "1.0.3", diff --git a/api/package.json b/api/package.json index 58cb1cf27..ab961c78c 100644 --- a/api/package.json +++ b/api/package.json @@ -1,6 +1,6 @@ { "name": "geli-api", - "version": "0.6.0", + "version": "0.7.0", "license": "GPL-3.0", "repository": "h-da/geli", "description": "This is the API-Package.json for geli.", @@ -25,78 +25,81 @@ "test": "istanbul cover --report json node_modules/mocha/bin/_mocha", "posttest": "gulp remap:coverage", "lint": "gulp tslint", + "lint:fix": "tslint --fix -c ./tslint.json 'src/**/*.ts'", "debug": "gulp debug", "load:fixtures": "gulp load:fixtures", "migrate": "gulp build && node ./build/src/migrate.js", "migrate:inspect": "gulp migrate:inspect" }, "dependencies": { + "@types/sharp": "^0.17.8", "app-root-path": "^2.0.1", - "archiver": "^2.1.0", + "archiver": "^2.1.1", "bcrypt": "^1.0.3", "body-parser": "^1.18.2", - "express": "^4.16.2", + "express": "^4.16.3", "fast-csv": "^2.4.1", - "fs-extra": "^4.0.3", - "jsonwebtoken": "^8.1.0", + "fs-extra": "^5.0.0", + "jsonwebtoken": "^8.2.1", "migrate-mongoose": "^3.2.2", - "moment": "^2.19.3", - "mongoose": "^4.13.6", + "moment": "^2.22.1", + "mongoose": "^5.0.17", "morgan": "^1.9.0", "multer": "^1.3.0", "node-file-cache": "^1.0.2", - "nodemailer": "^4.4.1", + "nodemailer": "^4.6.4", "nodemailer-markdown": "^1.0.2", "passport": "^0.4.0", - "passport-jwt": "^3.0.1", + "passport-jwt": "^4.0.0", "passport-local": "^1.0.0", - "raven": "^2.2.1", - "reflect-metadata": "^0.1.10", - "routing-controllers": "^0.7.6", + "raven": "^2.6.0", + "reflect-metadata": "^0.1.12", + "routing-controllers": "^0.7.7", + "sharp": "^0.20.1", "stream-buffers": "^3.0.1", "to-utf-8": "^1.3.0", - "validator": "^9.1.2", - "winston": "^2.4.0" + "validator": "^9.4.1", + "winston": "^2.4.2" }, "devDependencies": { "@types/bcrypt": "^1.0.0", "@types/body-parser": "1.16.8", - "@types/chai": "4.0.8", - "@types/chai-http": "3.0.3", - "@types/express": "4.0.39", - "@types/fs-extra": "^4.0.5", - "@types/jsonwebtoken": "^7.2.4", - "@types/mocha": "^2.2.44", - "@types/mongoose": "^4.7.28", + "@types/chai": "4.1.2", + "@types/chai-http": "3.0.4", + "@types/express": "4.11.1", + "@types/fs-extra": "^5.0.2", + "@types/jsonwebtoken": "^7.2.7", + "@types/mocha": "^5.2.0", + "@types/mongoose": "^5.0.12", "@types/morgan": "1.7.35", - "@types/nodemailer": "^4.3.1", - "@types/passport": "^0.4.1", - "@types/passport-jwt": "^3.0.0", - "@types/passport-local": "^1.0.32", - "@types/raven": "^2.1.2", - "@types/validator": "^6.3.0", - "@types/winston": "2.3.7", + "@types/nodemailer": "^4.6.0", + "@types/passport": "^0.4.5", + "@types/passport-jwt": "^3.0.1", + "@types/passport-local": "^1.0.33", + "@types/raven": "^2.5.1", + "@types/validator": "^9.4.1", + "@types/winston": "^2.3.9", "chai": "4.1.2", - "chai-http": "^3.0.0", - "coveralls": "^3.0.0", + "chai-http": "^4.0.0", + "coveralls": "^3.0.1", "gulp": "3.9.1", - "gulp-apidoc": "^0.2.6", - "gulp-istanbul": "1.1.2", - "gulp-mocha": "4.3.1", + "gulp-apidoc": "^0.2.7", + "gulp-istanbul": "1.1.3", + "gulp-mocha": "5.0.0", "gulp-nodemon": "2.2.1", - "gulp-plumber": "1.1.0", - "gulp-sourcemaps": "2.6.1", - "gulp-tslint": "8.1.2", - "gulp-typedoc": "2.1.1", - "gulp-typescript": "3.2.3", + "gulp-plumber": "1.2.0", + "gulp-sourcemaps": "2.6.4", + "gulp-tslint": "8.1.3", + "gulp-typedoc": "2.2.0", + "gulp-typescript": "4.0.2", "mocha-lcov-reporter": "^1.3.0", - "remap-istanbul": "0.9.5", + "remap-istanbul": "0.11.0", "rimraf": "2.6.2", - "run-sequence": "2.2.0", + "run-sequence": "2.2.1", "temp": "^0.8.3", - "tslint": "5.8.0", - "typedoc": "^0.9.0", - "typescript": "^2.6.2" + "tslint": "5.9.1", + "typedoc": "^0.11.1", + "typescript": "^2.8.3" }, "engines": { "node": ">=4.0.0" diff --git a/api/src/config/errorCodes.ts b/api/src/config/errorCodes.ts index b8a304752..21400b2aa 100644 --- a/api/src/config/errorCodes.ts +++ b/api/src/config/errorCodes.ts @@ -1,4 +1,6 @@ // TODO move to shared folder +import config from '../config/main'; + export const errorCodes = { mail: { duplicate: { @@ -32,6 +34,56 @@ export const errorCodes = { text: 'Incorrect or missing access key' } }, + user: { + cantChangeOwnRole: { + code: 'cantChangeOwnRole', + text: 'You can\'t change your own role.' + }, + emailAlreadyInUse: { + code: 'emailAlreadyInUse', + text: 'This email address is already in use.' + }, + invalidOldUserRole: { + code: 'invalidOldUserRole', + text: 'Invalid old user role.' + }, + invalidNewUserRole: { + code: 'invalidNewUserRole', + text: 'Invalid update role.' + }, + cantChangeUserWithHigherRole: { + code: 'cantChangeUserWithHigherRole', + text: 'You don\'t have the authorization to change a user of this role.' + }, + onlyAdminsCanChangeRoles: { + code: 'onlyAdminsCanChangeRoles', + text: 'Only users with admin privileges can change roles.' + }, + onlyAdminsCanChangeUids: { + code: 'onlyAdminsCanChangeUids', + text: 'Only users with admin privileges can change uids.' + }, + invalidPassword: { + code: 'invalidPassword', + text: 'Invalid current password!' + }, + noOtherAdmins: { + code: 'noOtherAdmins', + text: 'There are no other users with admin privileges.' + }, + userNotFound: { + code: 'user not found', + text: 'User was not found.', + }, + retryAfter: { + code: 'retry after', + text: 'You can only resend the activation every ' + config.timeTilNextActivationResendMin + ' minutes. You can resend again in ', + }, + userAlreadyActive: { + code: 'user already active', + text: 'User is already activated.' + } + }, whitelist: { duplicateWhitelistUser: { code: 'duplicate uid', diff --git a/api/src/config/main.ts b/api/src/config/main.ts index f505870a3..4678b34c2 100644 --- a/api/src/config/main.ts +++ b/api/src/config/main.ts @@ -37,4 +37,8 @@ export default { maxZipSize: 204800, uploadFolder: process.env.UPLOADFOLDER || (appRoot + '/uploads/'), + maxProfileImageWidth: 512, + maxProfileImageHeight: 512, + + timeTilNextActivationResendMin: 10, }; diff --git a/api/src/controllers/AuthController.ts b/api/src/controllers/AuthController.ts index a25d0dd9a..31efefb95 100644 --- a/api/src/controllers/AuthController.ts +++ b/api/src/controllers/AuthController.ts @@ -1,7 +1,7 @@ -import {Request} from 'express'; +import {Request, Response} from 'express'; import { Body, Post, JsonController, Req, HttpError, UseBefore, BodyParam, ForbiddenError, - InternalServerError, BadRequestError, OnUndefined + InternalServerError, BadRequestError, OnUndefined, Res } from 'routing-controllers'; import {json as bodyParserJson} from 'body-parser'; import passportLoginMiddleware from '../security/passportLoginMiddleware'; @@ -9,7 +9,7 @@ import emailService from '../services/EmailService'; import {IUser} from '../../../shared/models/IUser'; import {IUserModel, User} from '../models/User'; import {JwtUtils} from '../security/JwtUtils'; -import * as errorCodes from '../config/errorCodes' +import * as errorCodes from '../config/errorCodes'; import {Course} from '../models/Course'; import config from '../config/main'; @@ -136,6 +136,62 @@ export class AuthController { }); } + + /** + * @api {post} /api/auth/activationresend Resend Activation + * @apiName ActivationResend + * @apiGroup Auth + * + * @apiParam {string} lastname lastname of user which activation should be resend. + * @apiParam {string} uid matriculation number of user which activation should be resend. + * @apiParam {string} email email the new activation should be sent to. + * + * @apiError (BadRequestError) 400 User was not found. + * @apiError (BadRequestError) 400 That email address is already in use + * @apiError (BadRequestError) 400 User is already activated. + * @apiError (HttpError) 503 You can only resend the activation every X minutes. Your next chance is in + * time left till next try in 'try-after' header in seconds + * @apiError (InternalServerError) Could not send E-Mail + */ + @Post('/activationresend') + @OnUndefined(204) + async activationResend (@BodyParam('lastname') lastname: string, + @BodyParam('uid') uid: string, + @BodyParam('email') email: string, + @Res() response: Response) { + const user = await User.findOne({'profile.lastName': lastname, uid: uid, role: 'student'}); + + if (!user) { + throw new BadRequestError(errorCodes.errorCodes.user.userNotFound.code); + } + + if (user.isActive) { + throw new BadRequestError(errorCodes.errorCodes.user.userAlreadyActive.code); + } + + const timeSinceUpdate: number = (Date.now() - user.updatedAt.getTime() ) / 60000; + if (timeSinceUpdate < Number(config.timeTilNextActivationResendMin)) { + const retryAfter: number = (Number(config.timeTilNextActivationResendMin) - timeSinceUpdate) * 60; + response.set('retry-after', retryAfter.toString()); + throw new HttpError(503, errorCodes.errorCodes.user.retryAfter.code); + } + + const existingUser = await User.findOne({email: email}); + if (existingUser && existingUser.uid !== uid) { + throw new BadRequestError(errorCodes.errorCodes.mail.duplicate.code); + } + + user.authenticationToken = undefined; + user.email = email; + const savedUser = await user.save(); + + try { + await emailService.resendActivation(savedUser); + } catch (err) { + throw new InternalServerError(err.toString()); + } + } + /** * @api {post} /api/auth/reset Reset password * @apiName PostAuthReset diff --git a/api/src/controllers/ConfigController.ts b/api/src/controllers/ConfigController.ts index 1aa4b1358..71ba93af2 100644 --- a/api/src/controllers/ConfigController.ts +++ b/api/src/controllers/ConfigController.ts @@ -2,7 +2,7 @@ import { Authorized, Body, Get, InternalServerError, - JsonController, NotFoundError, + JsonController, Param, Put, UnauthorizedError, UseBefore @@ -11,7 +11,8 @@ import {Config} from '../models/Config'; import passportJwtMiddleware from '../security/passportJwtMiddleware'; const publicConfigs = [ - new RegExp('imprint') + new RegExp('imprint|infoBox'), + new RegExp('downloadMaxFileSize') ]; function publicConfig(id: string) { diff --git a/api/src/controllers/CourseController.ts b/api/src/controllers/CourseController.ts index ebde9f96e..fb0970c8b 100644 --- a/api/src/controllers/CourseController.ts +++ b/api/src/controllers/CourseController.ts @@ -13,25 +13,23 @@ import { UseBefore } from 'routing-controllers'; import passportJwtMiddleware from '../security/passportJwtMiddleware'; -import * as errorCodes from '../config/errorCodes' +import {errorCodes} from '../config/errorCodes'; import {ICourse} from '../../../shared/models/ICourse'; +import {ICourseDashboard} from '../../../shared/models/ICourseDashboard'; +import {ICourseView} from '../../../shared/models/ICourseView'; import {IUser} from '../../../shared/models/IUser'; import {ObsCsvController} from './ObsCsvController'; -import {Course, ICourseModel} from '../models/Course'; +import {Course} from '../models/Course'; import {User} from '../models/User'; import {WhitelistUser} from '../models/WhitelistUser'; import emailService from '../services/EmailService'; const multer = require('multer'); import crypto = require('crypto'); -import {IUnitModel} from '../models/units/Unit'; -import {API_NOTIFICATION_TYPE_ALL_CHANGES, API_NOTIFICATION_TYPE_NONE, NotificationSettings} from '../models/NotificationSettings'; -import {Notification} from '../models/Notification'; -import * as mongoose from 'mongoose'; -import {Schema} from 'mongoose'; -import ObjectId = mongoose.Types.ObjectId; +import {API_NOTIFICATION_TYPE_ALL_CHANGES, NotificationSettings} from '../models/NotificationSettings'; import {IWhitelistUser} from '../../../shared/models/IWhitelistUser'; +import {DocumentToObjectOptions} from 'mongoose'; const uploadOptions = { storage: multer.diskStorage({ @@ -62,72 +60,50 @@ export class CourseController { * * @apiParam {IUser} currentUser Currently logged in user. * - * @apiSuccess {Course[]} courses List of courses. + * @apiSuccess {ICourseDashboard[]} courses List of ICourseDashboard objects. * * @apiSuccessExample {json} Success-Response: * [ * { - * "_id": "5a037e6b60f72236d8e7c83b", - * "updatedAt": "2018-01-29T20:26:35.204Z", - * "createdAt": "2017-11-08T22:00:11.262Z", - * "name": "Advanced web development", - * "description": "Learn all the things! Angular, Node, Express, MongoDB, TypeScript ...", - * "courseAdmin": { - * "_id": "5a037e6a60f72236d8e7c817", - * "updatedAt": "2017-11-08T22:00:10.899Z", - * "createdAt": "2017-11-08T22:00:10.899Z", - * "email": "teacher4@test.local", - * "__v": 0, - * "isActive": true, - * "role": "teacher", - * "profile": { - * "firstName": "Severus", - * "lastName": "Snap" - * }, - * "id": "5a037e6a60f72236d8e7c817" - * }, - * "active": true, - * "__v": 3, - * "whitelist": [], + * "_id": "5ad0f9b56ff514268c5adc8c", + * "name": "Inactive Test", + * "active": false, + * "description": "An inactive course.", * "enrollType": "free", - * "lectures": [], - * "students": [], - * "teachers": [], - * "hasAccessKey": false + * "userCanEditCourse": true, + * "userCanViewCourse": true, + * "userIsCourseAdmin": true, + * "userIsCourseTeacher": false, + * "userIsCourseMember": true * }, * { - * "_id": "5a037e6b60f72236d8e7c83d", - * "updatedAt": "2017-11-08T22:00:11.869Z", - * "createdAt": "2017-11-08T22:00:11.263Z", - * "name": "Introduction to web development", - * "description": "Whether you're just getting started with Web development or are just expanding your horizons...", - * "courseAdmin": { - * "_id": "5a037e6a60f72236d8e7c815", - * "updatedAt": "2017-11-08T22:00:10.898Z", - * "createdAt": "2017-11-08T22:00:10.898Z", - * "email": "teacher2@test.local", - * "__v": 0, - * "isActive": true, - * "role": "teacher", - * "profile": { - * "firstName": "Ober", - * "lastName": "Lehrer" - * }, - * "id": "5a037e6a60f72236d8e7c815" - * }, + * "_id": "5ad0f9b56ff514268c5adc8d", + * "name": "Access key test", * "active": true, - * "__v": 1, - * "whitelist": [], + * "description": "This course is used to test the access key course enroll type.", + * "enrollType": "accesskey", + * "userCanEditCourse": true, + * "userCanViewCourse": true, + * "userIsCourseAdmin": false, + * "userIsCourseTeacher": true, + * "userIsCourseMember": true + * }, + * { + * "_id": "5ad0f9b56ff514268c5adc8e", + * "name": "Advanced web development", + * "active": true, + * "description": "Learn all the things! Angular, Node, Express, MongoDB, TypeScript ...", * "enrollType": "free", - * "lectures": [], - * "students": [], - * "teachers": [], - * "hasAccessKey": false + * "userCanEditCourse": false, + * "userCanViewCourse": false, + * "userIsCourseAdmin": false, + * "userIsCourseTeacher": false, + * "userIsCourseMember": false * } * ] */ @Get('/') - async getCourses(@CurrentUser() currentUser: IUser) { + async getCourses(@CurrentUser() currentUser: IUser): Promise { const whitelistUsers = await WhitelistUser.find({uid: currentUser.uid}); const conditions = this.userReadConditions(currentUser); if (conditions.$or) { @@ -137,108 +113,233 @@ export class CourseController { conditions.$or.push({enrollType: 'whitelist', whitelist: {$elemMatch: {$in: whitelistUsers}}}); } - const courses = await Course.find(conditions) - // TODO: Do not send lectures when student has no access - .populate('lectures') - .populate('teachers') - .populate('courseAdmin') - .populate('students'); + const courses = await Course.find(conditions); + return await Promise.all(courses.map(async (course) => { + return course.forDashboard(currentUser); + })); + } + + /** + * @api {get} /api/courses/:id Request view information for a specific course + * @apiName GetCourseView + * @apiGroup Course + * + * @apiParam {String} id Course ID. + * @apiParam {IUser} currentUser Currently logged in user. + * + * @apiSuccess {ICourseView} course ICourseView object. + * + * @apiSuccessExample {json} Success-Response: + * { + * "_id": "5ad0f9b56ff514268c5adc8d", + * "name": "Access key test", + * "description": "This course is used to test the access key course enroll type.", + * "lectures": [ + * { + * "units": [ + * { + * "__t": "free-text", + * "_id": "5ad0f9b56ff514268c5adc99", + * "updatedAt": "2018-04-13T18:40:53.305Z", + * "createdAt": "2018-04-13T18:40:53.305Z", + * "name": "What is the purpose of this course fixture?", + * "description": "", + * "markdown": "To test the 'accesskey' enrollType.", + * "_course": "5ad0f9b56ff514268c5adc8d", + * "__v": 0 + * } + * ], + * "_id": "5ad0f9b56ff514268c5adc92", + * "updatedAt": "2018-04-13T18:40:53.316Z", + * "createdAt": "2018-04-13T18:40:53.284Z", + * "name": "Documentation", + * "description": "Documents the course fixture.", + * "__v": 1 + * } + * ] + * } + * + * @apiError NotFoundError Includes implicit authorization check. (In getCourse helper method.) + * @apiError ForbiddenError (Redundant) Authorization check. + */ + @Get('/:id') + async getCourseView(@Param('id') id: string, @CurrentUser() currentUser: IUser): Promise { + const course = await this.getCourse(id, currentUser); - return courses.map(course => { - const courseObject: any = course.toObject(); - if (currentUser.role === 'student') { - delete courseObject.courseAdmin; + // This is currently a redundant check, because userReadConditions in getCourse above already restricts access! + // (I.e. just in case future changes break something.) + if (!course.checkPrivileges(currentUser).userCanViewCourse) { + throw new ForbiddenError(); + } - courseObject.students = courseObject.students.filter( - (student: any) => student._id === currentUser._id - ); - } - return courseObject; - }) + await course.populateLecturesFor(currentUser) + .populate('courseAdmin') + .populate('teachers') + .execPopulate(); + await course.processLecturesFor(currentUser); + return course.forView(); } /** - * @api {get} /api/courses/:id Request course with certain ID - * @apiName GetCourse + * @api {get} /api/courses/:id/edit Request edit information for a specific course + * @apiName GetCourseEdit * @apiGroup Course + * @apiPermission teacher + * @apiPermission admin * * @apiParam {String} id Course ID. * @apiParam {IUser} currentUser Currently logged in user. * - * @apiSuccess {Course} course Course. + * @apiSuccess {ICourse} course ICourse object. * * @apiSuccessExample {json} Success-Response: * { - * "_id": "5a037e6b60f72236d8e7c83d", - * "updatedAt": "2017-11-08T22:00:11.869Z", - * "createdAt": "2017-11-08T22:00:11.263Z", - * "name": "Introduction to web development", - * "description": "Whether you're just getting started with Web development or are just expanding your horizons...", + * "teachers": [ + * { + * "profile": { + * "lastName": "Teachman", + * "firstName": "Daniel" + * }, + * "role": "teacher", + * "lastVisitedCourses": [ + * "5ad0f9b56ff514268c5adc8d", + * "5ad0f9b56ff514268c5adc8b", + * "5ad0f9b56ff514268c5adc8c", + * "5ad2c3ba94e45c0c8493da06", + * "5ad7a43f943190432c5af597", + * "5ad0f9b56ff514268c5adc90" + * ], + * "isActive": true, + * "_id": "5ad0f9b56ff514268c5adc7e", + * "updatedAt": "2018-04-21T23:52:03.424Z", + * "createdAt": "2018-04-13T18:40:53.189Z", + * "email": "teacher1@test.local", + * "__v": 0, + * "id": "5ad0f9b56ff514268c5adc7e" + * } + * ], + * "students": [ + * { + * "profile": { + * "firstName": "Fabienne", + * "lastName": "Wiedenroth" + * }, + * "role": "student", + * "lastVisitedCourses": [], + * "isActive": true, + * "_id": "5ad0f9b56ff514268c5adc64", + * "updatedAt": "2018-04-13T18:40:53.108Z", + * "createdAt": "2018-04-13T18:40:53.108Z", + * "uid": "469952", + * "email": "student5@test.local", + * "__v": 0, + * "id": "5ad0f9b56ff514268c5adc64" + * }, + * { + * "profile": { + * "firstName": "Clemens", + * "lastName": "TillmannsEdit", + * "theme": "night" + * }, + * "role": "student", + * "lastVisitedCourses": [ + * "5ad0f9b56ff514268c5adc8b", + * "5ad0f9b56ff514268c5adc8d", + * "5ad0f9b56ff514268c5adc8e" + * ], + * "isActive": true, + * "_id": "5ad0f9b56ff514268c5adc76", + * "updatedAt": "2018-04-13T22:22:17.046Z", + * "createdAt": "2018-04-13T18:40:53.163Z", + * "uid": "970531", + * "email": "edit@test.local", + * "__v": 0, + * "id": "5ad0f9b56ff514268c5adc76" + * } + * ], + * "lectures": [ + * { + * "units": [ + * { + * "__t": "free-text", + * "_id": "5ad0f9b56ff514268c5adc99", + * "updatedAt": "2018-04-13T18:40:53.305Z", + * "createdAt": "2018-04-13T18:40:53.305Z", + * "name": "What is course fixture for?", + * "description": "", + * "markdown": "To test the 'accesskey' enrollType.", + * "_course": "5ad0f9b56ff514268c5adc8d", + * "__v": 0 + * } + * ], + * "_id": "5ad0f9b56ff514268c5adc92", + * "updatedAt": "2018-04-13T18:40:53.316Z", + * "createdAt": "2018-04-13T18:40:53.284Z", + * "name": "Documentation", + * "description": "Documents the course fixture.", + * "__v": 1 + * } + * ], + * "enrollType": "accesskey", + * "whitelist": [], + * "_id": "5ad0f9b56ff514268c5adc8d", + * "updatedAt": "2018-04-21T02:45:15.877Z", + * "createdAt": "2018-04-13T18:40:53.279Z", + * "name": "Access key test", + * "description": "This course is used to test the access key course enroll type.", + * "active": true, + * "accessKey": "accessKey1234", * "courseAdmin": { - * "_id": "5a037e6a60f72236d8e7c815", - * "updatedAt": "2017-11-08T22:00:10.898Z", - * "createdAt": "2017-11-08T22:00:10.898Z", - * "email": "teacher2@test.local", - * "isActive": true, - * "role": "teacher", * "profile": { * "firstName": "Ober", * "lastName": "Lehrer" * }, - * "id": "5a037e6a60f72236d8e7c815" + * "role": "teacher", + * "lastVisitedCourses": [], + * "isActive": true, + * "_id": "5ad0f9b56ff514268c5adc7f", + * "updatedAt": "2018-04-13T18:40:53.192Z", + * "createdAt": "2018-04-13T18:40:53.192Z", + * "email": "teacher2@test.local", + * "__v": 0, + * "id": "5ad0f9b56ff514268c5adc7f" * }, - * "active": true, - * "__v": 1, - * "whitelist": [], - * "enrollType": "free", - * "lectures": [], - * "students": [], - * "teachers": [], - * "id": "5a037e6b60f72236d8e7c83d", - * "hasAccessKey": false + * "__v": 6, + * "media": { + * "subDirectories": [], + * "files": [], + * "_id": "5ad2569171d8982ad0761451", + * "updatedAt": "2018-04-14T19:29:21.296Z", + * "createdAt": "2018-04-14T19:29:21.296Z", + * "name": "Access key test", + * "__v": 0 + * }, + * "hasAccessKey": true * } * - * @apiError NotFoundError + * @apiError NotFoundError Includes implicit authorization check. (In getCourse helper method.) + * @apiError ForbiddenError (Redundant) Authorization check. */ - @Get('/:id') - async getCourse(@Param('id') id: string, @CurrentUser() currentUser: IUser) { - const course = await Course.findOne({ - ...this.userReadConditions(currentUser), - _id: id - }) - // TODO: Do not send lectures when student has no access - .populate({ - path: 'lectures', - populate: { - path: 'units', - virtuals: true, - populate: { - path: 'progressData', - match: {user: {$eq: currentUser._id}} - } - } - }) + @Authorized(['teacher', 'admin']) + @Get('/:id([a-fA-F0-9]{24})/edit') + async getCourseEdit(@Param('id') id: string, @CurrentUser() currentUser: IUser): Promise { + const course = await this.getCourse(id, currentUser); + + // This is currently a redundant check, because userReadConditions in getCourse and @Authorized already restrict access! + // (I.e. just in case future changes break something.) + if (!course.checkPrivileges(currentUser).userCanEditCourse) { + throw new ForbiddenError(); + } + + await course.populateLecturesFor(currentUser) .populate('media') .populate('courseAdmin') .populate('teachers') .populate('students') .populate('whitelist') - .exec(); - - if (!course) { - throw new NotFoundError(); - } - - course.lectures = await Promise.all(course.lectures.map(async (lecture) => { - lecture.units = await Promise.all(lecture.units.map(async (unit: IUnitModel) => { - unit = await unit.populateUnit(); - return unit.secureData(currentUser); - })); - - return lecture; - })); - - return course.toObject(); + .execPopulate(); + await course.processLecturesFor(currentUser); + return course.toObject({currentUser}); } private userReadConditions(currentUser: IUser) { @@ -261,6 +362,19 @@ export class CourseController { return conditions; } + private async getCourse(id: string, currentUser: IUser) { + const course = await Course.findOne({ + ...this.userReadConditions(currentUser), + _id: id + }); + + if (!course) { + throw new NotFoundError(); + } + + return course; + } + /** * @api {post} /api/courses/ Add course * @apiName PostCourse @@ -309,16 +423,17 @@ export class CourseController { */ @Authorized(['teacher', 'admin']) @Post('/') - addCourse(@Body() course: ICourse, @Req() request: Request, @CurrentUser() currentUser: IUser) { + async addCourse(@Body() course: ICourse, @Req() request: Request, @CurrentUser() currentUser: IUser) { + // Note that this might technically have a race condition, but it should never matter because the new course ids remain unique. + // If a strict version is deemed important, see mongoose Model.findOneAndUpdate for a potential approach. + const existingCourse = await Course.findOne({name: course.name}); + if (existingCourse) { + throw new BadRequestError(errorCodes.course.duplicateName.code); + } course.courseAdmin = currentUser; - return Course.findOne({name: course.name}) - .then((existingCourse) => { - if (existingCourse) { - throw new BadRequestError(errorCodes.errorCodes.course.duplicateName.code); - } - return new Course(course).save() - .then((c) => c.toObject()); - }); + const newCourse = new Course(course); + await newCourse.save(); + return newCourse.toObject(); } /** @@ -367,38 +482,10 @@ export class CourseController { * @apiParam {Object} data Data (with access key). * @apiParam {IUser} currentUser Currently logged in user. * - * @apiSuccess {Course} course Enrolled course. + * @apiSuccess {{}} result Empty object. * * @apiSuccessExample {json} Success-Response: - * { - * "_id": "5a037e6b60f72236d8e7c83d", - * "updatedAt": "2017-11-08T22:00:11.869Z", - * "createdAt": "2017-11-08T22:00:11.263Z", - * "name": "Introduction to web development", - * "description": "Whether you're just getting started with Web development or are just expanding your horizons...", - * "courseAdmin": { - * "_id": "5a037e6a60f72236d8e7c815", - * "updatedAt": "2017-11-08T22:00:10.898Z", - * "createdAt": "2017-11-08T22:00:10.898Z", - * "email": "teacher2@test.local", - * "isActive": true, - * "role": "teacher", - * "profile": { - * "firstName": "Ober", - * "lastName": "Lehrer" - * }, - * "id": "5a037e6a60f72236d8e7c815" - * }, - * "active": true, - * "__v": 1, - * "whitelist": [], - * "enrollType": "free", - * "lectures": [], - * "students": [], - * "teachers": [], - * "id": "5a037e6b60f72236d8e7c83d", - * "hasAccessKey": false - * } + * {} * * @apiError NotFoundError * @apiError ForbiddenError Not allowed to join, you are not on whitelist. @@ -407,32 +494,33 @@ export class CourseController { @Authorized(['student']) @Post('/:id/enroll') async enrollStudent(@Param('id') id: string, @Body() data: any, @CurrentUser() currentUser: IUser) { - let course = await Course.findById(id); + const course = await Course.findById(id); if (!course) { - throw new NotFoundError(); - } - if (course.enrollType === 'whitelist') { - const wUsers: IWhitelistUser[] = await WhitelistUser.find().where({courseId: course._id}); - if (wUsers.filter(e => - e.firstName === currentUser.profile.firstName.toLowerCase() - && e.lastName === currentUser.profile.lastName.toLowerCase() - && e.uid === currentUser.uid).length <= 0) { - throw new ForbiddenError(errorCodes.errorCodes.course.notOnWhitelist.code); - } - } else if (course.accessKey && course.accessKey !== data.accessKey) { - throw new ForbiddenError(errorCodes.errorCodes.course.accessKey.code); - } + throw new NotFoundError(); + } + if (course.enrollType === 'whitelist') { + const wUsers: IWhitelistUser[] = await WhitelistUser.find().where({courseId: course._id}); + if (wUsers.filter(e => + e.firstName === currentUser.profile.firstName.toLowerCase() + && e.lastName === currentUser.profile.lastName.toLowerCase() + && e.uid === currentUser.uid).length <= 0) { + throw new ForbiddenError(errorCodes.course.notOnWhitelist.code); + } + } else if (course.accessKey && course.accessKey !== data.accessKey) { + throw new ForbiddenError(errorCodes.course.accessKey.code); + } - if (course.students.indexOf(currentUser._id) < 0) { - course.students.push(currentUser); - await new NotificationSettings({ - 'user': currentUser, 'course': course, - 'notificationType': API_NOTIFICATION_TYPE_ALL_CHANGES, - 'emailNotification': false - }).save(); - course = await course.save(); - } - return course.toObject(); + if (course.students.indexOf(currentUser._id) < 0) { + course.students.push(currentUser); + await new NotificationSettings({ + 'user': currentUser, + 'course': course, + 'notificationType': API_NOTIFICATION_TYPE_ALL_CHANGES, + 'emailNotification': false + }).save(); + await course.save(); + } + return {}; } /** @@ -445,58 +533,34 @@ export class CourseController { * @apiParam {Object} data Body. * @apiParam {IUser} currentUser Currently logged in user. * - * @apiSuccess {Course} course Left course. + * @apiSuccess {{}} result Empty object. * * @apiSuccessExample {json} Success-Response: - * { - * "_id": "5a037e6b60f72236d8e7c83d", - * "updatedAt": "2017-11-08T22:00:11.869Z", - * "createdAt": "2017-11-08T22:00:11.263Z", - * "name": "Introduction to web development", - * "description": "Whether you're just getting started with Web development or are just expanding your horizons...", - * "courseAdmin": { - * "_id": "5a037e6a60f72236d8e7c815", - * "updatedAt": "2017-11-08T22:00:10.898Z", - * "createdAt": "2017-11-08T22:00:10.898Z", - * "email": "teacher2@test.local", - * "isActive": true, - * "role": "teacher", - * "profile": { - * "firstName": "Ober", - * "lastName": "Lehrer" - * }, - * "id": "5a037e6a60f72236d8e7c815" - * }, - * "active": true, - * "__v": 1, - * "whitelist": [], - * "enrollType": "free", - * "lectures": [], - * "students": [], - * "teachers": [], - * "id": "5a037e6b60f72236d8e7c83d", - * "hasAccessKey": false - * } + * {} * * @apiError NotFoundError + * @apiError ForbiddenError */ @Authorized(['student']) @Post('/:id/leave') async leaveStudent(@Param('id') id: string, @Body() data: any, @CurrentUser() currentUser: IUser) { const course = await Course.findById(id); - if (!course) { - throw new NotFoundError(); - } - const index: number = course.students.indexOf(currentUser._id); - if (index >= 0) { - course.students.splice(index, 1); - await NotificationSettings.findOne({'user': currentUser, 'course': course}).remove(); - const savedCourse = await course.save(); - return savedCourse.toObject(); - } - return course.toObject(); + if (!course) { + throw new NotFoundError(); + } + const index: number = course.students.indexOf(currentUser._id); + if (index >= 0) { + course.students.splice(index, 1); + await NotificationSettings.findOne({'user': currentUser, 'course': course}).remove(); + await course.save(); + return {}; + } else { + // This equals an implicit !course.checkPrivileges(currentUser).userIsCourseStudent check. + throw new ForbiddenError(); + } } + /** * @api {post} /api/courses/:id/whitelist Whitelist students for course * @apiName PostCourseWhitelist @@ -507,56 +571,39 @@ export class CourseController { * @apiParam {String} id Course ID. * @apiParam {Object} file Uploaded file. * - * @apiSuccess {Course} course Updated course. + * @apiSuccess {Object} result Returns the new whitelist length. * * @apiSuccessExample {json} Success-Response: - * { - * "_id": "5a037e6b60f72236d8e7c83d", - * "updatedAt": "2018-01-29T23:43:07.220Z", - * "createdAt": "2017-11-08T22:00:11.263Z", - * "name": "Introduction to web development", - * "description": "Whether you're just getting started with Web development or are just expanding your horizons...", - * "courseAdmin": "5a037e6a60f72236d8e7c815", - * "active": true, - * "__v": 1, - * "whitelist": [{ - * "_bsontype": "ObjectID", - * "id": {...} - * },{ - * "_bsontype": "ObjectID", - * "id": {...} - * },{ - * "_bsontype": "ObjectID", - * "id": {...} - * }], - * "enrollType": "whitelist", - * "lectures": [], - * "students": [], - * "teachers": [], - * "hasAccessKey": false - * } + * { + * newlength: 10 + * } * - * @apiError TypeError Wrong type allowed are just csv files. + * @apiError TypeError Only CSV files are allowed. * @apiError HttpError UID is not a number 1. + * @apiError ForbiddenError Unauthorized user. */ - // TODO: Needs more security @Authorized(['teacher', 'admin']) @Post('/:id/whitelist') - whitelistStudents(@Param('id') id: string, @UploadedFile('file', {options: uploadOptions}) file: any) { + async whitelistStudents( + @Param('id') id: string, + @UploadedFile('file', {options: uploadOptions}) file: any, + @CurrentUser() currentUser: IUser) { const name: string = file.originalname; if (!name.endsWith('.csv')) { - throw new TypeError(errorCodes.errorCodes.upload.type.notCSV.code); + throw new TypeError(errorCodes.upload.type.notCSV.code); + } + const course = await Course.findById(id); + if (!course.checkPrivileges(currentUser).userCanEditCourse) { + throw new ForbiddenError(); } - return Course.findById(id) + await course .populate('whitelist') .populate('students') - .then((course) => { - return this.parser.parseFile(file).then((buffer: any) => - this.parser.updateCourseFromBuffer(buffer, course) - .then(c => c.save()) - .then((c: ICourseModel) => - c.toObject())); - }); + .execPopulate(); + const buffer = await this.parser.parseFile(file); + await this.parser.updateCourseFromBuffer(buffer, course); + await course.save(); + return {newlength: course.whitelist.length}; } /** @@ -570,29 +617,19 @@ export class CourseController { * @apiParam {ICourse} course New course data. * @apiParam {IUser} currentUser Currently logged in user. * - * @apiSuccess {Course} course Updated course. + * @apiSuccess {Object} result ID and name of the course. * * @apiSuccessExample {json} Success-Response: - * { - * "_id": "5a037e6b60f72236d8e7c83d", - * "updatedAt": "2018-01-29T23:43:07.220Z", - * "createdAt": "2017-11-08T22:00:11.263Z", - * "name": "Introduction to web development", - * "description": "Whether you're just getting started with Web development or are just expanding your horizons...", - * "courseAdmin": "5a037e6a60f72236d8e7c815", - * "active": true, - * "__v": 1, - * "whitelist": [], - * "enrollType": "free", - * "lectures": [], - * "students": [], - * "teachers": [], - * "hasAccessKey": false - * } + * { + * _id: "5a037e6b60f72236d8e7c83d", + * name: "Introduction to web development" + * } + * + * @apiError NotFoundError Can't find the course. (Includes implicit authorization check.) */ @Authorized(['teacher', 'admin']) @Put('/:id') - updateCourse(@Param('id') id: string, @Body() course: ICourse, @CurrentUser() currentUser: IUser) { + async updateCourse(@Param('id') id: string, @Body() course: ICourse, @CurrentUser() currentUser: IUser) { const conditions: any = {_id: id}; if (currentUser.role !== 'admin') { conditions.$or = [ @@ -600,17 +637,12 @@ export class CourseController { {courseAdmin: currentUser._id} ]; } - return Course.findOneAndUpdate( - conditions, - course, - {'new': true} - ) - .then((c) => { - if (c) { - return c.toObject(); - } - return undefined; - }); + const updatedCourse = await Course.findOneAndUpdate(conditions, course, {'new': true}); + if (updatedCourse) { + return {_id: updatedCourse.id, name: updatedCourse.name}; + } else { + throw new NotFoundError(); + } } /** @@ -621,30 +653,25 @@ export class CourseController { * @apiParam {String} id Course ID. * @apiParam {IUser} currentUser Currently logged in user. * - * @apiSuccess {Boolean} result Confirmation of deletion. + * @apiSuccess {{}} result Empty object. * * @apiSuccessExample {json} Success-Response: - * { - * "result": true - * } + * {} * * @apiError NotFoundError - * @apiError ForbiddenError Forbidden! + * @apiError ForbiddenError */ @Authorized(['teacher', 'admin']) @Delete('/:id') async deleteCourse(@Param('id') id: string, @CurrentUser() currentUser: IUser) { - const course = await Course.findOne({_id: id}); + const course = await Course.findById(id); if (!course) { throw new NotFoundError(); } - const courseAdmin = await User.findOne({_id: course.courseAdmin}); - if (course.teachers.indexOf(currentUser._id) !== -1 || courseAdmin.equals(currentUser._id.toString()) - || currentUser.role === 'admin') { - await course.remove(); - return {result: true}; - } else { - throw new ForbiddenError('Forbidden!'); + if (!course.checkPrivileges(currentUser).userCanEditCourse) { + throw new ForbiddenError(); } + await course.remove(); + return {}; } } diff --git a/api/src/controllers/DownloadController.ts b/api/src/controllers/DownloadController.ts index e0fb719d8..6dbce8559 100644 --- a/api/src/controllers/DownloadController.ts +++ b/api/src/controllers/DownloadController.ts @@ -20,6 +20,7 @@ const fs = require('fs'); const archiver = require('archiver'); import crypto = require('crypto'); import {User} from '../models/User'; +import {File} from '../models/mediaManager/File'; const cache = require('node-file-cache').create({life: config.timeToLiveCacheValue}); @@ -196,31 +197,21 @@ export class DownloadController { let unitCounter = 1; for (const unit of lec.units) { - const localUnit = await Unit.findOne({_id: unit.unitId}); - if (localUnit.__t === 'free-text') { - const freeTextUnit = localUnit; - archive.append(await FreeTextUnit.schema.statics.toFile(freeTextUnit), { - name: lecCounter + '_' + lcName + '/' + unitCounter + '_' + this.replaceCharInFilename(freeTextUnit.name) + '.md' - }); - } else if (localUnit.__t === 'code-kata') { - const codeKataUnit = localUnit; - archive.append(await CodeKataUnit.schema.statics.toFile(codeKataUnit), - {name: lecCounter + '_' + lcName + '/' + unitCounter + '_' + this.replaceCharInFilename(codeKataUnit.name) + '.txt'}); - } else if (localUnit.__t === 'file') { - const fileUnit = localUnit; - fileUnit.files.forEach((file, index) => { - if (unit.files.indexOf(index) > -1) { - archive.file(file.link, {name: lecCounter + '_' + lcName + '/' + unitCounter + '_' + file.name}); - } - }); - } else if (localUnit.__t === 'task') { - const taskUnit = localUnit; - archive.append(await TaskUnit.schema.statics.toFile(taskUnit), - {name: lecCounter + '_' + lcName + '/' + unitCounter + '_' + this.replaceCharInFilename(taskUnit.name) + '.txt'}); - } else { + + if (!localUnit) { throw new NotFoundError(); } + + if (localUnit.__t === 'file') { + for (const fileId of unit.files) { + const file = await File.findById(fileId); + archive.file( 'uploads/' + file.link, {name: lecCounter + '_' + lcName + '/' + unitCounter + '_' + file.name}); + } + } else { + archive.append(localUnit.toFile(), + {name: lecCounter + '_' + lcName + '/' + unitCounter + '_' + this.replaceCharInFilename(localUnit.name) + '.txt'}); + } unitCounter++; } lecCounter++; diff --git a/api/src/controllers/DuplicationController.ts b/api/src/controllers/DuplicationController.ts index 6335f2fd8..63da2f27d 100644 --- a/api/src/controllers/DuplicationController.ts +++ b/api/src/controllers/DuplicationController.ts @@ -55,7 +55,8 @@ export class DuplicationController { const courseAdmin = data.courseAdmin; try { const courseModel: ICourseModel = await Course.findById(id); - const exportedCourse: ICourse = await courseModel.exportJSON(); + const exportedCourse: ICourse = await courseModel.exportJSON(false); + delete exportedCourse.students; return Course.schema.statics.importJSON(exportedCourse, courseAdmin); } catch (err) { const newError = new InternalServerError('Failed to duplicate course'); diff --git a/api/src/controllers/NotificationController.ts b/api/src/controllers/NotificationController.ts index 56e550379..382f97091 100644 --- a/api/src/controllers/NotificationController.ts +++ b/api/src/controllers/NotificationController.ts @@ -81,7 +81,7 @@ export class NotificationController { @Post('/user/:id') async createNotificationForStudent(@Param('id') userId: string, @Body() data: any) { const user = await User.findById(userId); - await this.createNotification(user, data.text, data.changedCourse, data.changedLecture, data.changedUnit) + await this.createNotification(user, data.text, data.changedCourse, data.changedLecture, data.changedUnit); return {notified: true}; } @@ -190,7 +190,7 @@ export class NotificationController { .populate('changedLecture') .populate('changedUnit'); return notifications.map(notification => { - return notification.toObject() + return notification.toObject(); }); } diff --git a/api/src/controllers/NotificationSettingsController.ts b/api/src/controllers/NotificationSettingsController.ts index 500e16795..f66cb20d5 100644 --- a/api/src/controllers/NotificationSettingsController.ts +++ b/api/src/controllers/NotificationSettingsController.ts @@ -82,7 +82,7 @@ export class NotificationSettingsController { @Put('/:id') async updateNotificationSettings(@Param('id') id: string, @Body() notificationSettings: INotificationSettings) { if (!notificationSettings) { - throw new BadRequestError('notification needs fields course and user') + throw new BadRequestError('notification needs fields course and user'); } const settings: INotificationSettingsModel = await NotificationSettings.findOneAndUpdate({'_id': id}, notificationSettings, {new: true}); diff --git a/api/src/controllers/ReportController.ts b/api/src/controllers/ReportController.ts index 460250a74..b40ab2985 100644 --- a/api/src/controllers/ReportController.ts +++ b/api/src/controllers/ReportController.ts @@ -89,7 +89,7 @@ export class ReportController { { name: 'tried', value: progressStats.tried }, { name: 'done', value: progressStats.done } ]; - }) + }); }); return courseObj; @@ -246,7 +246,7 @@ export class ReportController { return { ...userProgress, progresses: remappedProgresses - } + }; }); const studentsWithUnitsAndProgress = await students.map((student: IUser) => { @@ -577,9 +577,9 @@ export class ReportController { .map(({courseObj, progressableUnitCount}: any) => { const progressStats = this.calculateProgress(userProgressData, progressableUnitCount, courseObj); courseObj.progressData = [ - { name: 'nothing', value: progressStats.nothing }, + { name: 'not tried', value: progressStats.nothing }, { name: 'tried', value: progressStats.tried }, - { name: 'done', value: progressStats.done } + { name: 'solved', value: progressStats.done } ]; return courseObj; }) diff --git a/api/src/controllers/UnitController.ts b/api/src/controllers/UnitController.ts index 50847c2e1..e4c1b8b42 100644 --- a/api/src/controllers/UnitController.ts +++ b/api/src/controllers/UnitController.ts @@ -1,12 +1,13 @@ import { Body, Get, Put, Delete, Param, JsonController, UseBefore, NotFoundError, BadRequestError, Post, - Authorized + Authorized, CurrentUser } from 'routing-controllers'; import passportJwtMiddleware from '../security/passportJwtMiddleware'; import {Lecture} from '../models/Lecture'; import {IUnitModel, Unit} from '../models/units/Unit'; import {ValidationError} from 'mongoose'; +import {IUser} from '../../../shared/models/IUser'; @JsonController('/units') @UseBefore(passportJwtMiddleware) @@ -30,14 +31,19 @@ export class UnitController { * "description": "...", * "markdown": "# What is Lorem Ipsum?\n**Lorem Ipsum** is simply dummy text of the printing and typesetting industry.", * "_course": "5a037e6b60f72236d8e7c83b", + * "unitCreator": "5a037e6b60f72236d8e7c834", * "type": "free-text", * "__v": 0 * } */ @Get('/:id') - getUnit(@Param('id') id: string) { - return Unit.findById(id) - .then((u) => u.toObject()); + async getUnit(@Param('id') id: string) { + const unit = await Unit.findById(id); + + if (unit) { + throw new NotFoundError(); + } + return unit; } /** @@ -62,6 +68,7 @@ export class UnitController { * "markdown": "# What is Lorem Ipsum?\n**Lorem Ipsum** is simply dummy text of the printing and typesetting industry.", * "_course": "5a037e6b60f72236d8e7c83b", * "type": "free-text", + * "unitCreator": "5a037e6b60f72236d8e7c834", * "__v": 0 * } * @@ -74,21 +81,21 @@ export class UnitController { */ @Authorized(['teacher', 'admin']) @Post('/') - addUnit(@Body() data: any) { + async addUnit(@Body() data: any, @CurrentUser() currentUser: IUser) { // discard invalid requests this.checkPostParam(data); - - return Unit.create(data.model) - .then((createdUnit) => { - return this.pushToLecture(data.lectureId, createdUnit); - }) - .catch((err) => { + // Set current user as creator, old unit's dont have a creator + data.model.unitCreator = currentUser._id; + try { + const createdUnit = await Unit.create(data.model); + return await this.pushToLecture(data.lectureId, createdUnit); + } catch (err) { if (err.name === 'ValidationError') { throw err; } else { throw new BadRequestError(err); } - }); + } } /** diff --git a/api/src/controllers/UserController.ts b/api/src/controllers/UserController.ts index 8a02cc53e..44ef218cd 100644 --- a/api/src/controllers/UserController.ts +++ b/api/src/controllers/UserController.ts @@ -1,6 +1,6 @@ import { Body, JsonController, UseBefore, Get, Param, QueryParam, Put, Delete, Authorized, CurrentUser, - BadRequestError, ForbiddenError, UploadedFile, Post + BadRequestError, ForbiddenError, InternalServerError, NotFoundError, UploadedFile, Post } from 'routing-controllers'; import passportJwtMiddleware from '../security/passportJwtMiddleware'; import fs = require('fs'); @@ -8,6 +8,8 @@ import {IUser} from '../../../shared/models/IUser'; import {IUserModel, User} from '../models/User'; import {isNullOrUndefined} from 'util'; import {errorCodes} from '../config/errorCodes'; +import * as sharp from 'sharp'; +import config from '../config/main'; const multer = require('multer'); @@ -86,17 +88,17 @@ export class UserController { */ @Get('/') @Authorized(['teacher', 'admin']) - getUsers(@CurrentUser() currentUser?: IUser) { - return User.find({}) - .then((users) => { - return users.map((user) => this.cleanUserObject(null, user, currentUser)); - }); + async getUsers(@CurrentUser() currentUser: IUser) { + const users = await User.find(); + return users.map(user => user.forUser(currentUser)); } /** * @api {get} /api/users/members/search Request users with certain role and query * @apiName SearchUser * @apiGroup User + * @apiPermission teacher + * @apiPermission admin * * @apiParam {String="student","teacher"} role User role. * @apiParam {String} query Query string. @@ -173,7 +175,10 @@ export class UserController { * @apiError BadRequestError Query was empty. */ @Get('/members/search') // members/search because of conflict with /:id - async searchUser(@QueryParam('role') role: string, @QueryParam('query') query: string, @QueryParam('limit') limit?: number) { + @Authorized(['teacher', 'admin']) + async searchUser( + @CurrentUser() currentUser: IUser, @QueryParam('role') role: string, + @QueryParam('query') query: string, @QueryParam('limit') limit?: number) { if (role !== 'student' && role !== 'teacher') { throw new BadRequestError('Method not allowed for this role.'); } @@ -190,7 +195,7 @@ export class UserController { conditions.$or.push({uid: {$regex: re}}); conditions.$or.push({email: {$regex: re}}); conditions.$or.push({'profile.firstName': {$regex: re}}); - conditions.$or.push({'profile.lastName': {$regex: re}}) + conditions.$or.push({'profile.lastName': {$regex: re}}); }); const amountUsers = await User.count({}).where({role: role}); const users = await User.find(conditions, { @@ -200,7 +205,7 @@ export class UserController { .limit(limit ? limit : Number.MAX_SAFE_INTEGER) .sort({'score': {$meta: 'textScore'}}); return { - users: users.map((user) => user.toObject({virtuals: true})), + users: users.map(user => user.forUser(currentUser)), meta: { count: amountUsers } @@ -240,6 +245,8 @@ export class UserController { * * @apiSuccess {User} user User. * + * @apiError NotFoundError User was not found. + * * @apiSuccessExample {json} Success-Response: * { * "_id": "5a037e6a60f72236d8e7c81d", @@ -262,13 +269,14 @@ export class UserController { * "id": "5a037e6a60f72236d8e7c81d" * } */ - @Get('/:id') - getUser(@Param('id') id: string, @CurrentUser() currentUser?: IUser) { - return User.findById(id) - .populate('progress') - .then((user) => { - return this.cleanUserObject(id, user, currentUser); - }); + @Get('/:id([a-fA-F0-9]{24})') + async getUser(@Param('id') id: string, @CurrentUser() currentUser?: IUser) { + const user = await User.findById(id).populate('progress'); + + if (!user) { + throw new NotFoundError(`User was not found.`); + } + return user.forUser(currentUser); } /** @@ -277,8 +285,7 @@ export class UserController { * @apiGroup User * * @apiParam {Object} file Uploaded file. - * @apiParam {String} id User ID. - * @apiParam {Object} data Body. + * @apiParam {String} id User target ID. * @apiParam {IUser} currentUser Currently logged in user. * * @apiSuccess {User} user Affected user. @@ -305,41 +312,68 @@ export class UserController { * "id": "5a037e6a60f72236d8e7c81d" * } * + * @apiError ForbiddenError Forbidden format of uploaded picture. + * @apiError ForbiddenError You don't have the authorization to change a user of this role. * @apiError BadRequestError */ @Post('/picture/:id') - addUserPicture(@UploadedFile('file', {options: uploadOptions}) file: any, @Param('id') id: string, @Body() data: any, - @CurrentUser() currentUser: IUser) { - return User.findById(id) - .then((user: IUserModel) => { - if (user.profile.picture && user.profile.picture.link && fs.existsSync(user.profile.picture.link)) { - fs.unlinkSync(user.profile.picture.link); - } + async addUserPicture( + @UploadedFile('file', {options: uploadOptions}) file: any, + @Param('id') id: string, @CurrentUser() currentUser: IUser) { + const mimeFamily = file.mimetype.split('/', 1)[0]; + if (mimeFamily !== 'image') { + throw new ForbiddenError('Forbidden format of uploaded picture: ' + mimeFamily); + } + + let user = await User.findById(id); + + if (!user.checkEditableBy(currentUser).editAllowed) { + throw new ForbiddenError(errorCodes.user.cantChangeUserWithHigherRole.text); + } - user.profile.picture = { - _id: null, - name: file.originalname, - link: file.filename, - size: file.size, - mimeType: file.mimeType - }; - return user.save(); - }) - .then((user) => { - return this.cleanUserObject(id, user, currentUser); - }) - .catch((error) => { - throw new BadRequestError(error); - }); + if (user.profile.picture) { + const path = user.profile.picture.path; + if (path && fs.existsSync(path)) { + fs.unlinkSync(path); + } + } + + const resizedImageBuffer = + await sharp(file.path) + .resize(config.maxProfileImageWidth, config.maxProfileImageHeight) + .withoutEnlargement(true) + .max() + .toBuffer({resolveWithObject: true}); + + fs.writeFileSync(file.path, resizedImageBuffer.data); + + user.profile.picture = { + _id: null, + name: file.filename, + alias: file.originalname, + path: file.path, + size: resizedImageBuffer.info.size + }; + + try { + user = await user.save(); + } catch (error) { + throw new BadRequestError(error); + } + + return user.forUser(currentUser); } /** * @api {put} /api/users/:id Update user * @apiName PutUser * @apiGroup User + * @apiPermission student + * @apiPermission teacher + * @apiPermission admin * - * @apiParam {String} id User ID. - * @apiParam {Object} user New user data. + * @apiParam {String} id User target ID. + * @apiParam {Object} newUser New user data. * @apiParam {IUser} currentUser Currently logged in user. * * @apiSuccess {User} user Updated user. @@ -366,61 +400,65 @@ export class UserController { * "id": "5a037e6a60f72236d8e7c81d" * } * - * @apiError BadRequestError You can't revoke your own privileges. - * @apiError BadRequestError This mail address is already in use. - * @apiError BadRequestError Invalid Current Password! + * @apiError BadRequestError Invalid update role. + * @apiError BadRequestError You can't change your own role. + * @apiError BadRequestError This email address is already in use. + * @apiError BadRequestError Invalid current password! + * @apiError ForbiddenError You don't have the authorization to change a user of this role. * @apiError ForbiddenError Only users with admin privileges can change roles. * @apiError ForbiddenError Only users with admin privileges can change uids. */ + @Authorized(['student', 'teacher', 'admin']) @Put('/:id') - updateUser(@Param('id') id: string, @Body() user: any, @CurrentUser() currentUser?: IUser) { - return User.find({'role': 'admin'}) - .then((adminUsers) => { - if (id === currentUser._id - && currentUser.role === 'admin' - && user.role !== 'admin') { - throw new BadRequestError('You can\'t revoke your own privileges'); - } else { - return User.find({$and: [{'email': user.email}, {'_id': {$ne: user._id}}]}); - } - }) - .then((emailInUse) => { - if (emailInUse.length > 0) { - throw new BadRequestError('This mail address is already in use.'); - } else { - return User.findById(id); - } - }) - .then((oldUser: IUserModel) => { - if (user.role !== oldUser.role && currentUser.role !== 'admin') { - throw new ForbiddenError('Only users with admin privileges can change roles'); - } else if (user.uid !== oldUser.uid && currentUser.role !== 'admin') { - throw new ForbiddenError('Only users with admin privileges can change uids'); - } else { - if (oldUser.uid && user.uid === null) { - user.uid = oldUser.uid; - } + async updateUser(@Param('id') id: string, @Body() newUser: any, @CurrentUser() currentUser: IUser) { + if (id === currentUser._id && currentUser.role !== newUser.role) { + throw new BadRequestError(errorCodes.user.cantChangeOwnRole.text); + } + + const oldUser = await User.findById(id); + const {userIsAdmin, editAllowed} = oldUser.checkEditableBy(currentUser); - return oldUser.isValidPassword(user.currentPassword); - } - }) - .then((isValidPassword) => { - if (typeof user.password !== 'undefined') { - if (!(currentUser.role === 'admin' && currentUser._id !== user._id) && !isValidPassword && user.password.length > 0) { - throw new BadRequestError('Invalid Current Password!'); - } else { - if (user.password.length === 0) { - delete user.password; - } - return User.findOneAndUpdate({'_id': id}, user, {new: true}); - } - } else { - return User.findOneAndUpdate({'_id': id}, user, {new: true}); - } - }) - .then((updatedUser) => { - return updatedUser.toObject({virtuals: true}); - }); + if (!editAllowed) { + throw new ForbiddenError(errorCodes.user.cantChangeUserWithHigherRole.text); + } + + if (oldUser.uid && newUser.uid === null) { + newUser.uid = oldUser.uid; + } + if (oldUser.role && typeof newUser.role === 'undefined') { + newUser.role = oldUser.role; + } else if (typeof User.getEditLevelUnsafe(newUser) === 'undefined') { + throw new BadRequestError(errorCodes.user.invalidNewUserRole.text); + } + + if (!userIsAdmin) { + if (newUser.role !== oldUser.role) { + throw new ForbiddenError(errorCodes.user.onlyAdminsCanChangeRoles.text); + } + if (newUser.uid !== oldUser.uid) { + throw new ForbiddenError(errorCodes.user.onlyAdminsCanChangeUids.text); + } + } + + if (typeof newUser.password === 'undefined' || newUser.password.length === 0) { + delete newUser.password; + } else { + const isValidPassword = await oldUser.isValidPassword(newUser.currentPassword); + if (!isValidPassword) { + throw new BadRequestError(errorCodes.user.invalidPassword.text); + } + } + + { + const sameEmail = {$and: [{'email': newUser.email}, {'_id': {$ne: newUser._id}}]}; + const users = await User.find(sameEmail).limit(1); + if (users.length > 0) { + throw new BadRequestError(errorCodes.user.emailAlreadyInUse.text); + } + } + + const updatedUser = await User.findOneAndUpdate({_id: id}, newUser, {new: true}); + return updatedUser.forUser(currentUser); } /** @@ -442,27 +480,14 @@ export class UserController { */ @Authorized('admin') @Delete('/:id') - deleteUser(@Param('id') id: string) { - return User.find({'role': 'admin'}) - .then((adminUsers) => { - if (adminUsers.length === 1 && - adminUsers[0].get('id') === id && - adminUsers[0].role === 'admin') { - throw new BadRequestError('There are no other users with admin privileges.'); - } else { - return User.findByIdAndRemove(id); - } - }) - .then(() => { - return {result: true}; - }); - } - - private cleanUserObject(id: string, user: IUserModel, currentUser?: IUser) { - user.password = ''; - if (currentUser._id !== id && (currentUser.role !== 'teacher' || currentUser.role !== 'admin')) { - user.uid = null; + async deleteUser(@Param('id') id: string, @CurrentUser() currentUser: IUser) { + if (id === currentUser._id) { + const otherAdmin = await User.findOne({$and: [{'role': 'admin'}, {'_id': {$ne: id}}]}); + if (otherAdmin === null) { + throw new BadRequestError(errorCodes.user.noOtherAdmins.text); + } } - return user.toObject({virtuals: true}); + await User.findByIdAndRemove(id); + return {result: true}; } } diff --git a/api/src/controllers/WhitelistController.ts b/api/src/controllers/WhitelistController.ts index 04df7bd36..e25d380d8 100644 --- a/api/src/controllers/WhitelistController.ts +++ b/api/src/controllers/WhitelistController.ts @@ -185,6 +185,6 @@ export class WitelistController { lastName: whitelistUser.lastName, uid: whitelistUser.uid, courseId: new ObjectId(whitelistUser.courseId) - } + }; } } diff --git a/api/src/migrate.ts b/api/src/migrate.ts index 24494d1ed..6f148e9cc 100644 --- a/api/src/migrate.ts +++ b/api/src/migrate.ts @@ -21,7 +21,7 @@ if (process.argv.length === 3) { .then((res) => { console.log(res); console.log('Disconnect'); - mongoose.disconnect() + mongoose.disconnect(); }); } diff --git a/api/src/migrations/MigrationHandler.ts b/api/src/migrations/MigrationHandler.ts index cf6d6ef93..055644736 100644 --- a/api/src/migrations/MigrationHandler.ts +++ b/api/src/migrations/MigrationHandler.ts @@ -13,7 +13,7 @@ export class MigrationHandler { (mongoose).Promise = global.Promise; if (!mongoose.connection.readyState) { - this.databaseConnection = mongoose.connect(config.database, {useMongoClient: true}); + this.databaseConnection = mongoose.connect(config.database); } fs.readdirSync(__dirname + '/scripts').forEach((file: string) => { diff --git a/api/src/models/Course.ts b/api/src/models/Course.ts index aac29f4fd..7cfab2926 100644 --- a/api/src/models/Course.ts +++ b/api/src/models/Course.ts @@ -1,17 +1,32 @@ import {ICourse} from '../../../shared/models/ICourse'; +import {ICourseDashboard} from '../../../shared/models/ICourseDashboard'; +import {ICourseView} from '../../../shared/models/ICourseView'; import * as mongoose from 'mongoose'; -import {User} from './User'; +import {User, IUserModel} from './User'; import {ILectureModel, Lecture} from './Lecture'; import {ILecture} from '../../../shared/models/ILecture'; import {InternalServerError} from 'routing-controllers'; import {IUser} from '../../../shared/models/IUser'; import * as winston from 'winston'; import {ObjectID} from 'bson'; +import {Directory} from './mediaManager/Directory'; +import {IProperties} from '../../../shared/models/IProperties'; +import {extractMongoId} from '../utilities/ExtractMongoId'; interface ICourseModel extends ICourse, mongoose.Document { - exportJSON: () => Promise; + exportJSON: (sanitize?: boolean) => Promise; + checkPrivileges: (user: IUser) => IProperties; + forDashboard: (user: IUser) => ICourseDashboard; + forView: () => ICourseView; + populateLecturesFor: (user: IUser) => this; + processLecturesFor: (user: IUser) => Promise; } +interface ICourseMongoose extends mongoose.Model { +} + +let Course: ICourseMongoose; + const courseSchema = new mongoose.Schema({ name: { type: String, @@ -29,10 +44,10 @@ const courseSchema = new mongoose.Schema({ ref: 'User' }, media: - { - type: mongoose.Schema.Types.ObjectId, - ref: 'Directory' - }, + { + type: mongoose.Schema.Types.ObjectId, + ref: 'Directory' + }, teachers: [ { type: mongoose.Schema.Types.ObjectId, @@ -69,7 +84,7 @@ const courseSchema = new mongoose.Schema({ { timestamps: true, toObject: { - transform: function (doc: any, ret: any) { + transform: function (doc: ICourseModel, ret: any, {currentUser}: { currentUser?: IUser }) { if (ret.hasOwnProperty('_id') && ret._id !== null) { ret._id = ret._id.toString(); } @@ -81,36 +96,59 @@ const courseSchema = new mongoose.Schema({ if (ret.accessKey) { ret.hasAccessKey = true; } + + if (currentUser !== undefined) { + if (doc.populated('teachers') !== undefined) { + ret.teachers = doc.teachers.map((user: IUserModel) => user.forUser(currentUser)); + } + if (doc.populated('students') !== undefined) { + ret.students = doc.students.map((user: IUserModel) => user.forUser(currentUser)); + } + } } } } ); // Cascade delete -courseSchema.pre('remove', function (next: () => void) { - Lecture.find({'_id': {$in: this.lectures}}).exec() - .then((lectures) => Promise.all(lectures.map(lecture => lecture.remove()))) - .then(next) - .catch(next); +courseSchema.pre('remove', async function () { + const localCourse = this; + try { + const dic = await Directory.findById(localCourse.media); + if (dic) { + await dic.remove(); + } + for (const lec of localCourse.lectures) { + const lecDoc = await Lecture.findById(lec); + await lecDoc.remove(); + } + } catch (error) { + winston.log('warn', 'course (' + localCourse._id + ') cloud not be deleted!'); + throw new Error('Delete Error: ' + error.toString()); + } }); -courseSchema.methods.exportJSON = async function () { +courseSchema.methods.exportJSON = async function (sanitize: boolean = true) { const obj = this.toObject(); // remove unwanted informations - // mongo properties - delete obj._id; - delete obj.createdAt; - delete obj.__v; - delete obj.updatedAt; - - // custom properties - delete obj.accessKey; - delete obj.active; - delete obj.whitelist; - delete obj.students; - delete obj.courseAdmin; - delete obj.teachers; + { + // mongo properties + delete obj._id; + delete obj.createdAt; + delete obj.__v; + delete obj.updatedAt; + + // custom properties + if (sanitize) { + delete obj.accessKey; + delete obj.active; + delete obj.whitelist; + delete obj.students; + delete obj.courseAdmin; + delete obj.teachers; + } + } // "populate" lectures const lectures: Array = obj.lectures; @@ -168,6 +206,83 @@ courseSchema.statics.importJSON = async function (course: ICourse, admin: IUser, } }; -const Course = mongoose.model('Course', courseSchema); + +courseSchema.methods.checkPrivileges = function (user: IUser) { + const {userIsAdmin, ...userIs} = User.checkPrivileges(user); + + const courseAdminId = extractMongoId(this.courseAdmin); + + const userIsCourseAdmin: boolean = user._id === courseAdminId; + const userIsCourseTeacher: boolean = this.teachers.some((teacher: IUserModel) => user._id === extractMongoId(teacher)); + const userIsCourseStudent: boolean = this.students.some((student: IUserModel) => user._id === extractMongoId(student)); + const userIsCourseMember: boolean = userIsCourseAdmin || userIsCourseTeacher || userIsCourseStudent; + + const userCanEditCourse: boolean = userIsAdmin || userIsCourseAdmin || userIsCourseTeacher; + const userCanViewCourse: boolean = (this.active && userIsCourseStudent) || userCanEditCourse; + + return { + userIsAdmin, ...userIs, + courseAdminId, + userIsCourseAdmin, userIsCourseTeacher, userIsCourseStudent, userIsCourseMember, + userCanEditCourse, userCanViewCourse + }; +}; + +courseSchema.methods.forDashboard = function (user: IUser): ICourseDashboard { + const { + name, active, description, enrollType + } = this; + const { + userCanEditCourse, userCanViewCourse, userIsCourseAdmin, userIsCourseTeacher, userIsCourseMember + } = this.checkPrivileges(user); + return { + // As in ICourse: + _id: extractMongoId(this._id), + name, active, description, enrollType, + + // Special properties for the dashboard: + userCanEditCourse, userCanViewCourse, userIsCourseAdmin, userIsCourseTeacher, userIsCourseMember + }; +}; + +courseSchema.methods.forView = function (): ICourseView { + const { + name, description, + courseAdmin, teachers, + lectures + } = this; + return { + _id: extractMongoId(this._id), + name, description, + courseAdmin: User.forCourseView(courseAdmin), + teachers: teachers.map((teacher: IUser) => User.forCourseView(teacher)), + lectures: lectures.map((lecture: any) => lecture.toObject()) + }; +}; + +courseSchema.methods.populateLecturesFor = function (user: IUser) { + const isTeacherOrAdmin = (user.role === 'teacher' || user.role === 'admin'); + return this.populate({ + path: 'lectures', + populate: { + path: 'units', + virtuals: true, + match: {$or: [{visible: undefined}, {visible: true}, {visible: !isTeacherOrAdmin}]}, + populate: { + path: 'progressData', + match: {user: {$eq: user._id}} + } + } + }); +}; + +courseSchema.methods.processLecturesFor = async function (user: IUser) { + this.lectures = await Promise.all(this.lectures.map(async (lecture: ILectureModel) => { + return await lecture.processUnitsFor(user); + })); + return this; +}; + +Course = mongoose.model('Course', courseSchema); export {Course, ICourseModel}; diff --git a/api/src/models/Lecture.ts b/api/src/models/Lecture.ts index d27e2eeec..97106f156 100644 --- a/api/src/models/Lecture.ts +++ b/api/src/models/Lecture.ts @@ -2,12 +2,14 @@ import * as mongoose from 'mongoose'; import {ILecture} from '../../../shared/models/ILecture'; import {IUnitModel, Unit} from './units/Unit'; import {IUnit} from '../../../shared/models/units/IUnit'; +import {IUser} from '../../../shared/models/IUser'; import {InternalServerError} from 'routing-controllers'; import {Course} from './Course'; import * as winston from 'winston'; interface ILectureModel extends ILecture, mongoose.Document { exportJSON: () => Promise; + processUnitsFor: (user: IUser) => Promise; } const lectureSchema = new mongoose.Schema({ @@ -36,16 +38,17 @@ const lectureSchema = new mongoose.Schema({ ); // Cascade delete -lectureSchema.pre('remove', function(next: () => void) { - // We cannot do this, because we need actual Unit instances so that their pre remove middleware gets called - // Unit.remove({'_id': {$in: this.units}}).exec().then(next).catch(next); - Unit.find({'_id': {$in: this.units}}).exec() - .then((units) => Promise.all(units.map(unit => unit.remove()))) - .then(next) - .catch(next); +lectureSchema.pre('remove', async function () { + const localLecture = this; + try { + await Unit.deleteMany({'_id': {$in: localLecture.units}}).exec(); + } catch (err) { + throw new Error('Delete Error: ' + err.toString()); + } + }); -lectureSchema.methods.exportJSON = async function() { +lectureSchema.methods.exportJSON = async function () { const obj = this.toObject(); // remove unwanted informations @@ -56,7 +59,7 @@ lectureSchema.methods.exportJSON = async function() { delete obj.updatedAt; // "populate" lectures - const units: Array = obj.units; + const units: Array = obj.units; obj.units = []; for (const unitId of units) { @@ -72,9 +75,17 @@ lectureSchema.methods.exportJSON = async function() { return obj; }; -lectureSchema.statics.importJSON = async function(lecture: ILecture, courseId: string) { +lectureSchema.methods.processUnitsFor = async function (user: IUser) { + this.units = await Promise.all(this.units.map(async (unit: IUnitModel) => { + unit = await unit.populateUnit(); + return unit.secureData(user); + })); + return this; +}; + +lectureSchema.statics.importJSON = async function (lecture: ILecture, courseId: string) { // importTest lectures - const units: Array = lecture.units; + const units: Array = lecture.units; lecture.units = []; try { diff --git a/api/src/models/User.ts b/api/src/models/User.ts index ce68ebeb1..1cf127e30 100644 --- a/api/src/models/User.ts +++ b/api/src/models/User.ts @@ -1,19 +1,44 @@ import * as mongoose from 'mongoose'; import * as bcrypt from 'bcrypt'; import {IUser} from '../../../shared/models/IUser'; +import {IUserSubSafe} from '../../../shared/models/IUserSubSafe'; +import {IUserSubTeacher} from '../../../shared/models/IUserSubTeacher'; +import {IUserSubCourseView} from '../../../shared/models/IUserSubCourseView'; import {NativeError} from 'mongoose'; import * as crypto from 'crypto'; import {isNullOrUndefined} from 'util'; import {isEmail} from 'validator'; -import * as errorCodes from '../config/errorCodes' +import {errorCodes} from '../config/errorCodes'; +import {IProperties} from '../../../shared/models/IProperties'; +import {extractMongoId} from '../utilities/ExtractMongoId'; +import {ensureMongoToObject} from '../utilities/EnsureMongoToObject'; interface IUserModel extends IUser, mongoose.Document { isValidPassword: (candidatePassword: string) => Promise; + checkPrivileges: () => IProperties; + checkEditUser: (targetUser: IUser) => IProperties; + checkEditableBy: (currentUser: IUser) => IProperties; + forSafe: () => IUserSubSafe; + forTeacher: () => IUserSubTeacher; + forCourseView: () => IUserSubCourseView; + forUser: (otherUser: IUser) => IUserSubSafe | IUserSubTeacher | IUser; authenticationToken: string; resetPasswordToken: string; resetPasswordExpires: Date; isActive: boolean; + updatedAt: Date; } +interface IUserMongoose extends mongoose.Model { + getEditLevel: (user: IUser) => number; + getEditLevelUnsafe: (user: any) => number | undefined; + checkPrivileges: (user: IUser) => IProperties; + checkEditUser: (currentUser: IUser, targetUser: IUser) => IProperties; + forSafe: (user: IUser | IUserModel) => IUserSubSafe; + forTeacher: (user: IUser | IUserModel) => IUserSubTeacher; + forCourseView: (user: IUser | IUserModel) => IUserSubCourseView; + forUser: (user: IUser | IUserModel, otherUser: IUser) => IUserSubSafe | IUserSubTeacher | IUser; +} +let User: IUserMongoose; const userSchema = new mongoose.Schema({ uid: { @@ -34,11 +59,19 @@ const userSchema = new mongoose.Schema({ password: { type: String, required: true, - validate: new RegExp(errorCodes.errorCodes.password.regex.regex) + validate: new RegExp(errorCodes.password.regex.regex) }, profile: { - firstName: {type: String, index: true}, - lastName: {type: String, index: true}, + firstName: { + type: String, + index: true, + maxlength: 64 + }, + lastName: { + type: String, + index: true, + maxlength: 64 + }, picture: { path: {type: String}, name: {type: String}, @@ -57,7 +90,8 @@ const userSchema = new mongoose.Schema({ authenticationToken: {type: String}, resetPasswordToken: {type: String}, resetPasswordExpires: {type: Date}, - isActive: {type: Boolean, 'default': false} + isActive: {type: Boolean, 'default': false}, + updatedAt: { type: Date, required: true, default: Date.now } }, { timestamps: true, @@ -92,8 +126,8 @@ function hashPassword(next: (err?: NativeError) => void) { } function generateActivationToken(next: (err?: NativeError) => void) { - // check if user is new and wasn't activated by the creator - if (this.isNew && !this.isActive && isNullOrUndefined(this.authenticationToken)) { + // check if user wasn't activated by the creator + if ( !this.isActive && isNullOrUndefined(this.authenticationToken)) { // set new authenticationToken this.authenticationToken = generateSecureToken(); } @@ -154,5 +188,132 @@ userSchema.methods.isValidPassword = function (candidatePassword: string) { return bcrypt.compare(candidatePassword, this.password); }; -const User = mongoose.model('User', userSchema); +userSchema.methods.checkPrivileges = function (): IProperties { + return User.checkPrivileges(this); +}; + +userSchema.methods.checkEditUser = function (targetUser: IUser): IProperties { + return User.checkEditUser(this, targetUser); +}; + +userSchema.methods.checkEditableBy = function (currentUser: IUser): IProperties { + return User.checkEditUser(currentUser, this); +}; + +userSchema.methods.forSafe = function (): IUserSubSafe { + return User.forSafe(this); +}; + +userSchema.methods.forTeacher = function (): IUserSubTeacher { + return User.forTeacher(this); +}; + +userSchema.methods.forCourseView = function (): IUserSubCourseView { + return User.forCourseView(this); +}; + +userSchema.methods.forUser = function (otherUser: IUser): IUserSubSafe | IUserSubTeacher | IUser { + return User.forUser(this, otherUser); +}; + +// The idea behind the editLevels is to only allow updates if the currentUser "has a higher level" than the target. +// (Or when the currentUser is an admin or targets itself.) +const editLevels: {[key: string]: number} = { + student: 0, + teacher: 0, + admin: 2, +}; + +userSchema.statics.getEditLevel = function (user: IUser): number { + return editLevels[user.role]; +}; + +userSchema.statics.getEditLevelUnsafe = function (user: any): number | undefined { + return editLevels[user.role]; +}; + +userSchema.statics.checkPrivileges = function (user: IUser): IProperties { + const userIsAdmin: boolean = user.role === 'admin'; + const userIsTeacher: boolean = user.role === 'teacher'; + const userIsStudent: boolean = user.role === 'student'; + // NOTE: The 'tutor' role exists and has fixtures, but currently appears to be unimplemented. + // const userIsTutor: boolean = user.role === 'tutor'; + + const userEditLevel: number = User.getEditLevel(user); + + return {userIsAdmin, userIsTeacher, userIsStudent, userEditLevel}; +}; + +userSchema.statics.checkEditUser = function (currentUser: IUser, targetUser: IUser): IProperties { + const {userIsAdmin} = User.checkPrivileges(currentUser); + + const currentEditLevel = User.getEditLevel(currentUser); + const targetEditLevel = User.getEditLevel(targetUser); + + const editSelf = extractMongoId(currentUser._id) === extractMongoId(targetUser._id); + const editLevelHigher = currentEditLevel > targetEditLevel; + + // Note that editAllowed only means authorization to edit SOME (herein unspecified) properties. + // If false, it serves as a definite indicator that absolutely NO edit access is to be granted, + // but if true, it by itself is not enough information to know what exactly is allowed. + // (I.e. it DOES NOT mean unrestricted editing capabilties.) + const editAllowed = userIsAdmin || editSelf || editLevelHigher; + + return { + userIsAdmin, + currentEditLevel, targetEditLevel, + editSelf, editLevelHigher, + editAllowed + }; +}; + +userSchema.statics.forSafe = function (user: IUser | IUserModel): IUserSubSafe { + const { + profile: {firstName, lastName} + } = user; + const result: IUserSubSafe = { + _id: extractMongoId(user._id), + profile: {firstName, lastName} + }; + const picture = ensureMongoToObject(user.profile.picture); + if (Object.keys(picture).length) { + result.profile.picture = picture; + } + return result; +}; + +userSchema.statics.forTeacher = function (user: IUser | IUserModel): IUserSubTeacher { + const { + uid, email + } = user; + return { + ...User.forSafe(user), + uid, email + }; +}; + +userSchema.statics.forCourseView = function (user: IUser | IUserModel): IUserSubCourseView { + const { + email + } = user; + return { + ...User.forSafe(user), + email + }; +}; + +userSchema.statics.forUser = function (user: IUser | IUserModel, otherUser: IUser): IUserSubSafe | IUserSubTeacher | IUser { + const {userIsTeacher, userIsAdmin} = User.checkPrivileges(otherUser); + const isSelf = extractMongoId(user._id) === extractMongoId(otherUser._id); + if (isSelf || userIsAdmin) { + return ensureMongoToObject(user); + } else if (userIsTeacher) { + return User.forTeacher(user); + } else { + return User.forSafe(user); + } +}; + +User = mongoose.model('User', userSchema); + export {User, IUserModel}; diff --git a/api/src/models/mediaManager/Directory.ts b/api/src/models/mediaManager/Directory.ts index 92b509327..98c760ef7 100644 --- a/api/src/models/mediaManager/Directory.ts +++ b/api/src/models/mediaManager/Directory.ts @@ -24,42 +24,46 @@ const directorySchema = new mongoose.Schema({ } ] }, { - timestamps: true, - toObject: { - transform: function (doc: IDirectoryModel, ret: any) { - ret._id = ret._id.toString(); - ret.subDirectories = ret.subDirectories.map((dir: any) => { - if (!dir._id) { - dir = dir.toString(); - } - return dir; - }); - ret.files = ret.files.map((file: any) => { - if (!file._id) { - file = file.toString(); - } - return file; - }); - } - }, + timestamps: true, + toObject: { + transform: function (doc: IDirectoryModel, ret: any) { + ret._id = ret._id.toString(); + ret.subDirectories = ret.subDirectories.map((dir: any) => { + if (!dir._id) { + dir = dir.toString(); + } + return dir; + }); + ret.files = ret.files.map((file: any) => { + if (!file._id) { + file = file.toString(); + } + return file; + }); + } + }, }); -directorySchema.pre('remove', async function(next: () => void) { - for (const subdir of this.subDirectories) { - // linting won't let us use 'Directory' before it is actually declared - // tslint:disable-next-line:no-use-before-declare - const model = await Directory.findById(subdir); - if (model) { - await model.remove(); +directorySchema.pre('remove', async function () { + const localDir = this; + try { + for (const subdir of localDir.subDirectories) { + // linting won't let us use 'Directory' before it is actually declared + // tslint:disable-next-line:no-use-before-declare + const model = await Directory.findById(subdir); + if (model) { + await model.remove(); + } } - } - for (const file of this.files) { - const model = await File.findById(file); - if (model) { - await model.remove(); + for (const file of localDir.files) { + const model = await File.findById(file); + if (model) { + await model.remove(); + } } + } catch (err) { + throw new Error('Delete Error: ' + err.toString()); } - next(); }); const Directory = mongoose.model('Directory', directorySchema); diff --git a/api/src/models/mediaManager/File.ts b/api/src/models/mediaManager/File.ts index 29a86c1d6..e363d886d 100644 --- a/api/src/models/mediaManager/File.ts +++ b/api/src/models/mediaManager/File.ts @@ -40,21 +40,23 @@ const fileSchema = new mongoose.Schema({ }, }); -fileSchema.pre('remove', async function(next: () => void) { - if (fs.existsSync(this.physicalPath)) { - await promisify(fs.unlink)(this.physicalPath); - } - - const units2Check: IFileUnitModel[] = await FileUnit.find({files: { $in: [ this._id ] }}); - Promise.all(units2Check.map(async unit => { - const index = unit.files.indexOf(this._id); - if (index > -1) { - unit.files.splice(index, 1); - await unit.save(); +fileSchema.pre('remove', async function() { + const localFile = this; + try { + if (fs.existsSync(localFile.physicalPath)) { + await promisify(fs.unlink)(localFile.physicalPath); } - })); - - next(); + const units2Check: IFileUnitModel[] = await FileUnit.find({files: {$in: [localFile._id]}}); + Promise.all(units2Check.map(async unit => { + const index = unit.files.indexOf(localFile._id); + if (index > -1) { + unit.files.splice(index, 1); + await unit.save(); + } + })); + } catch (err) { + throw new Error('Delete Error: ' + err.toString()); + } }); const File = mongoose.model('File', fileSchema); diff --git a/api/src/models/progress/TaskUnitProgress.ts b/api/src/models/progress/TaskUnitProgress.ts index 886077a68..394d498ee 100644 --- a/api/src/models/progress/TaskUnitProgress.ts +++ b/api/src/models/progress/TaskUnitProgress.ts @@ -16,19 +16,21 @@ const taskUnitProgressSchema = new mongoose.Schema({ ); taskUnitProgressSchema.pre('save', async function (next: () => void) { - const taskUnit = await Unit.findById(this.unit); + const localProg = this; + const taskUnit = await Unit.findById(localProg.unit); - this.done = true; + localProg.done = true; taskUnit.tasks.forEach(question => { question.answers.forEach(answer => { if ( - !this.answers[question._id.toString()] || - this.answers[question._id.toString()][answer._id.toString()] !== !!answer.value // !! is necessary, because value can be undefined + // !! is necessary, because value can be undefined + !localProg.answers[question._id.toString()] || + localProg.answers[question._id.toString()][answer._id.toString()] !== !!answer.value ) { - this.done = false; + localProg.done = false; } - }) + }); }); next(); diff --git a/api/src/models/units/CodeKataUnit.ts b/api/src/models/units/CodeKataUnit.ts index e17d94909..d1cc5edf0 100644 --- a/api/src/models/units/CodeKataUnit.ts +++ b/api/src/models/units/CodeKataUnit.ts @@ -9,7 +9,7 @@ interface ICodeKataModel extends ICodeKataUnit, IUnitModel { exportJSON: () => Promise; calculateProgress: () => Promise; secureData: (user: IUser) => Promise; - toFile: () => Promise; + toFile: () => String; } const codeKataSchema = new mongoose.Schema({ @@ -98,9 +98,15 @@ function validateTestArea(testArea: any) { codeKataSchema.pre('validate', splitCodeAreas); codeKataSchema.path('test').validate(validateTestArea); -codeKataSchema.statics.toFile = async function (unit: ICodeKataUnit) { - return unit.description + '\n' + unit.definition + '\n' + - unit.code + '\n' + unit.test; +codeKataSchema.methods.toFile = function (): String { + return this.description + '\n' + + '####################################' + + '\n' + this.definition + '\n' + + + '####################################' + + '\n' + + this.code + '\n' + + '####################################' + + '\n' + this.test; }; -export {codeKataSchema, ICodeKataModel} +export {codeKataSchema, ICodeKataModel}; diff --git a/api/src/models/units/FileUnit.ts b/api/src/models/units/FileUnit.ts index f9b8bc6b3..21ab2937f 100644 --- a/api/src/models/units/FileUnit.ts +++ b/api/src/models/units/FileUnit.ts @@ -1,10 +1,11 @@ import * as mongoose from 'mongoose'; import {IUnitModel} from './Unit'; import {IFileUnit} from '../../../../shared/models/units/IFileUnit'; +import {User} from '../User'; interface IFileUnitModel extends IFileUnit, IUnitModel { populateUnit: () => Promise; - toFile: () => Promise; + toFile: () => String; } const fileUnitSchema = new mongoose.Schema({ @@ -28,7 +29,14 @@ const fileUnitSchema = new mongoose.Schema({ }); fileUnitSchema.methods.populateUnit = async function() { + if (this.unitCreator) { + this.unitCreator = await User.findById(this.unitCreator); + } return this.populate('files').execPopulate(); }; -export {fileUnitSchema, IFileUnitModel} +fileUnitSchema.methods.toFile = function() { + return ''; +}; + +export {fileUnitSchema, IFileUnitModel}; diff --git a/api/src/models/units/FreeTextUnit.ts b/api/src/models/units/FreeTextUnit.ts index 657172be6..5309337ab 100644 --- a/api/src/models/units/FreeTextUnit.ts +++ b/api/src/models/units/FreeTextUnit.ts @@ -4,7 +4,7 @@ import {IFreeTextUnit} from '../../../../shared/models/units/IFreeTextUnit'; interface IFreeTextUnitModel extends IFreeTextUnit, IUnitModel { exportJSON: () => Promise; - toFile: () => Promise; + toFile: () => String; } const freeTextUnitSchema = new mongoose.Schema({ @@ -13,8 +13,8 @@ const freeTextUnitSchema = new mongoose.Schema({ } }); -freeTextUnitSchema.statics.toFile = async function (unit: IFreeTextUnit) { - return unit.name + '\n' + unit.description + '\n' + unit.markdown; +freeTextUnitSchema.methods.toFile = function (): String { + return this.name + '\n' + this.description + '\n' + this.markdown; }; -export {freeTextUnitSchema, IFreeTextUnitModel} +export {freeTextUnitSchema, IFreeTextUnitModel}; diff --git a/api/src/models/units/TaskUnit.ts b/api/src/models/units/TaskUnit.ts index b7b959f46..5e277e9b2 100644 --- a/api/src/models/units/TaskUnit.ts +++ b/api/src/models/units/TaskUnit.ts @@ -9,7 +9,7 @@ import {ITask} from '../../../../shared/models/task/ITask'; interface ITaskUnitModel extends ITaskUnit, IUnitModel { exportJSON: () => Promise; calculateProgress: (users: IUser[], progress: IProgress[]) => Promise; - toFile: () => Promise; + toFile: () => String; } const taskSchema = new mongoose.Schema( @@ -102,10 +102,10 @@ taskUnitSchema.methods.calculateProgress = async function (users: IUser[], progr return unitObj; }; -taskUnitSchema.statics.toFile = async function(unit: ITaskUnit) { +taskUnitSchema.methods.toFile = function(): String { let fileStream = ''; - for (const task of unit.tasks) { + for (const task of this.tasks) { fileStream = fileStream + task.name + '\n'; for (const answer of task.answers) { @@ -115,9 +115,7 @@ taskUnitSchema.statics.toFile = async function(unit: ITaskUnit) { } - return new Promise((resolve) => { - return resolve(fileStream); - }); + return fileStream; }; export {taskUnitSchema, ITaskUnitModel}; diff --git a/api/src/models/units/Unit.ts b/api/src/models/units/Unit.ts index 07928a0f5..11a080498 100644 --- a/api/src/models/units/Unit.ts +++ b/api/src/models/units/Unit.ts @@ -10,13 +10,14 @@ import {fileUnitSchema} from './FileUnit'; import {taskUnitSchema} from './TaskUnit'; import {IUser} from '../../../../shared/models/IUser'; import {IProgress} from '../../../../shared/models/progress/IProgress'; +import {User} from '../User'; interface IUnitModel extends IUnit, mongoose.Document { exportJSON: () => Promise; calculateProgress: (users: IUser[], progress: IProgress[]) => Promise; populateUnit: () => Promise; secureData: (user: IUser) => Promise; - toFile: () => Promise; + toFile: () => String; } const unitSchema = new mongoose.Schema({ @@ -39,12 +40,20 @@ const unitSchema = new mongoose.Schema({ }, type: { type: String + }, + visible: { + type: Boolean + }, + unitCreator: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User' } }, { collection: 'units', timestamps: true, toObject: { + virtuals: true, transform: function (doc: IUnitModel, ret: any) { ret._id = ret._id.toString(); ret._course = ret._course.toString(); @@ -60,7 +69,7 @@ unitSchema.virtual('progressData', { justOne: true }); -unitSchema.methods.exportJSON = function() { +unitSchema.methods.exportJSON = function () { const obj = this.toObject(); // remove unwanted informations @@ -76,19 +85,29 @@ unitSchema.methods.exportJSON = function() { return obj; }; -unitSchema.methods.calculateProgress = async function(): Promise { +unitSchema.methods.calculateProgress = async function (): Promise { return this.toObject(); }; -unitSchema.methods.populateUnit = async function(): Promise { +unitSchema.methods.populateUnit = async function (): Promise { + if (this.unitCreator) { + this.unitCreator = await User.findById(this.unitCreator); + } return this; }; -unitSchema.methods.secureData = async function(user: IUser): Promise { +unitSchema.methods.secureData = async function (user: IUser): Promise { + if (this.unitCreator) { + this.unitCreator = User.forSafe(this.unitCreator); + } return this; }; -unitSchema.statics.importJSON = async function(unit: IUnit, courseId: string, lectureId: string) { +unitSchema.methods.toFile = function (): String { + return ''; +}; + +unitSchema.statics.importJSON = async function (unit: IUnit, courseId: string, lectureId: string) { unit._course = courseId; try { @@ -109,8 +128,12 @@ unitSchema.statics.importJSON = async function(unit: IUnit, courseId: string, le }; // Cascade delete -unitSchema.pre('remove', function(next: () => void) { - Progress.remove({'unit': this._id}).exec().then(next).catch(next); +unitSchema.pre('remove', async function () { + try { + await Progress.remove({'unit': this._id}).exec(); + } catch (err) { + throw new Error('Delete Error: ' + err.toString()); + } }); const Unit = mongoose.model('Unit', unitSchema); diff --git a/api/src/server.ts b/api/src/server.ts index 25d204f6e..5a165b313 100644 --- a/api/src/server.ts +++ b/api/src/server.ts @@ -38,6 +38,8 @@ export class Server { // Do not use mpromise (mongoose).Promise = global.Promise; + // mongoose.set('debug', true); + this.app = createExpressServer({ routePrefix: '/api', controllers: [__dirname + '/controllers/*.js'], // register all controller's routes @@ -60,7 +62,7 @@ export class Server { } start() { - mongoose.connect(config.database, {useMongoClient: true}); + mongoose.connect(config.database); // Request logger this.app.use(morgan('combined')); diff --git a/api/src/services/EmailService.ts b/api/src/services/EmailService.ts index b82bff170..bbab98875 100644 --- a/api/src/services/EmailService.ts +++ b/api/src/services/EmailService.ts @@ -39,7 +39,7 @@ class EmailService { this.transporter = nodemailer.createTransport(this.mailTransportConfig, this.mailDefaultConfig); this.transporter.use('compile', markdown()); - }; + } public sendActivation(user: IUserModel) { if (!user) { @@ -66,6 +66,33 @@ class EmailService { return this.sendMail(message); } + public resendActivation(user: IUserModel) { + if (!user) { + throw new Error('user not defined'); + } + if (!user.authenticationToken) { + throw new Error('this user has no authenticationToken defined'); + } + + const message: SendMailOptions = {}; + + message.to = user.profile.firstName + ' ' + user.profile.lastName + '<' + user.email + '>'; + message.subject = 'Welcome again to GELI :)'; + message.text = 'Hello ' + user.profile.firstName + ', \n\n' + + 'you requested a new email verification. Your previous email verification link is invalid from now on.\n' + + 'Please use the following link to verify your E-Mail:\n' + + config.baseurl + '/activate/' + encodeURIComponent(user.authenticationToken) + '\n\n' + + 'Your GELI Team.'; + message.html = '

Hello ' + user.profile.firstName + ',


' + + '

you requested a new email verification. Your previous email verification link is invalid from now on.
' + + 'Please use the following link to verify your E-Mail:
' + + `` + config.baseurl + '/activate/' + encodeURIComponent(user.authenticationToken) + '


' + + '

Your GELI Team.

'; + + return this.sendMail(message); + } + public sendPasswordReset(user: IUserModel) { if (!user) { throw new Error('user not defined'); diff --git a/api/src/utilities/EnsureMongoToObject.ts b/api/src/utilities/EnsureMongoToObject.ts new file mode 100644 index 000000000..a2d342814 --- /dev/null +++ b/api/src/utilities/EnsureMongoToObject.ts @@ -0,0 +1,17 @@ +import {DocumentToObjectOptions, Document} from 'mongoose'; + +type Model = T & Document; + +/** + * Either calls the mongoose toObject function and returns the result, or simply returns the input. + * + * @param from A mongoose object with toObject function or any other object already returned by toObject (or similar). + * @param options Optional mongoose toObject options. + */ +export function ensureMongoToObject(from: T | Model, options?: DocumentToObjectOptions): T { + if ('toObject' in from && typeof from.toObject === 'function') { + return from.toObject(options); + } else { + return from; + } +} diff --git a/api/src/utilities/ExtractMongoId.ts b/api/src/utilities/ExtractMongoId.ts new file mode 100644 index 000000000..d9a0132a7 --- /dev/null +++ b/api/src/utilities/ExtractMongoId.ts @@ -0,0 +1,50 @@ +type implReturn = T | string | undefined; + +/** + * Tries to extract the id as string from any mongoose object. + * This could be a node-mongodb-native ObjectID (i.e. mongoose.Types.ObjectId), via toHexString, + * or anything that contains an 'id' property, which is directly returned. + * + * Any string input is assumed to be an ID and will be returned as string. + * + * @param from A mongoose object or id string. + * @param fallback Return this if no id is found. + */ +function extractMongoIdImpl(from: any, fallback?: T): implReturn { + if (typeof from === 'string' || from instanceof String) { + return from.toString(); + } else if (from instanceof Object) { + if (from._bsontype === 'ObjectID') { + return from.toString(); + } else if ('id' in from) { + return from.id; + } + } + return fallback; +} + +/** + * Tries to extract the id as string from any mongoose object or array of such. + * This could be a node-mongodb-native ObjectID (i.e. mongoose.Types.ObjectId), via toHexString, + * or anything that contains an 'id' property, which is directly returned. + * For arrays, anything === undefined won't be pushed. + * + * Any string input (or string array content) is assumed to be an ID. + * + * @param from A mongoose object, id string, or (possibly mixed) array of such. + * @param fallback Return this if no id is found. + */ +export function extractMongoId(from: any | any[], fallback?: T): implReturn | (T | string)[] { + if (Array.isArray(from)) { + const results: any[] = []; + for (const value of from) { + const result = extractMongoIdImpl(value, fallback); + if (result !== undefined) { + results.push(result); + } + } + return results; + } else { + return extractMongoIdImpl(from, fallback); + } +} diff --git a/api/src/utilities/Pick.ts b/api/src/utilities/Pick.ts new file mode 100644 index 000000000..70616d37a --- /dev/null +++ b/api/src/utilities/Pick.ts @@ -0,0 +1,22 @@ +import {IProperties} from '../../../shared/models/IProperties'; + +function only(keys: Array, from: IProperties, to: IProperties = {}) { + for (const key of keys) { + to[key] = from[key]; + } + return to; +} + +function asEmpty(keys: Array, from: IProperties, to: IProperties = {}) { + for (const key of keys) { + const value = from[key]; + if (Array.isArray(value)) { + to[key] = []; + } else if (value instanceof Object) { + to[key] = {}; + } + } + return to; +} + +export default {only, asEmpty}; diff --git a/api/test/controllers/TestNotificationController.ts b/api/test/controllers/TestNotificationController.ts index b10f5b1d9..99f31c060 100644 --- a/api/test/controllers/TestNotificationController.ts +++ b/api/test/controllers/TestNotificationController.ts @@ -13,7 +13,7 @@ chai.use(chaiHttp); const should = chai.should(); const app = new Server().app; const BASE_URL = '/api/notification'; -const fixtureLoader = new FixtureLoader() +const fixtureLoader = new FixtureLoader(); describe('Notifications', async () => { beforeEach(async () => { @@ -58,7 +58,7 @@ describe('Notifications', async () => { const notifications = await Notification.find({changedCourse: course}); notifications.length.should.be.equal(course.students.length); }); - }) + }); describe(`GET ${BASE_URL} user :id`, () => { it('should return all notifications for one user', async () => { @@ -78,8 +78,8 @@ describe('Notifications', async () => { notification._id.should.be.a('string'); notification.user._id.toString().should.be.equal(student._id.toString()); notification.text.should.be.a('string'); - }) - }) + }); + }); }); describe(`DELETE ${BASE_URL} :id`, () => { @@ -124,5 +124,5 @@ describe('Notifications', async () => { res.body.message.should.be.equal('Notification could not be found.'); }); - }) + }); }); diff --git a/api/test/controllers/TestNotificationSettingsController.ts b/api/test/controllers/TestNotificationSettingsController.ts index fe05c2c64..6f6a4d7c2 100644 --- a/api/test/controllers/TestNotificationSettingsController.ts +++ b/api/test/controllers/TestNotificationSettingsController.ts @@ -12,7 +12,7 @@ chai.use(chaiHttp); const should = chai.should(); const app = new Server().app; const BASE_URL = '/api/notificationSettings'; -const fixtureLoader = new FixtureLoader() +const fixtureLoader = new FixtureLoader(); describe('NotificationSettings', async () => { beforeEach(async () => { @@ -39,7 +39,7 @@ describe('NotificationSettings', async () => { const notificationSettings = await NotificationSettings.findById(res.body._id); notificationSettings.user.toString().should.be.equal(newSettings.user._id.toString()); notificationSettings.course.toString().should.be.equal(newSettings.course._id.toString()); - }) + }); }); describe(`GET ${BASE_URL} user :id`, () => { @@ -74,7 +74,7 @@ describe('NotificationSettings', async () => { notificationSettings.notificationType.should.be.a('string'); notificationSettings.emailNotification.should.be.a('boolean'); }); - }) + }); }); describe(`PUT ${BASE_URL} :id`, () => { @@ -101,7 +101,7 @@ describe('NotificationSettings', async () => { res.body.should.have.property('user'); res.body.should.have.property('course'); res.body._id.should.be.a('string'); - }) - }) + }); + }); }); diff --git a/api/test/integration/auth.ts b/api/test/integration/auth.ts index 2d46dcb5e..159c9d71b 100644 --- a/api/test/integration/auth.ts +++ b/api/test/integration/auth.ts @@ -2,12 +2,13 @@ import * as chai from 'chai'; import {Server} from '../../src/server'; import {FixtureLoader} from '../../fixtures/FixtureLoader'; import {User} from '../../src/models/User'; -import * as errorCodes from '../../src/config/errorCodes' +import * as errorCodes from '../../src/config/errorCodes'; import {WhitelistUser} from '../../src/models/WhitelistUser'; import {IUser} from '../../../shared/models/IUser'; import {Course} from '../../src/models/Course'; import {FixtureUtils} from '../../fixtures/FixtureUtils'; import chaiHttp = require('chai-http'); +import config from '../../src/config/main'; chai.use(chaiHttp); const should = chai.should(); @@ -15,6 +16,10 @@ const app = new Server().app; const BASE_URL = '/api/auth'; const fixtureLoader = new FixtureLoader(); +function delay(ms: number) { + return new Promise( resolve => setTimeout(resolve, ms) ); +} + describe('Auth', () => { // Before each test we reset the database beforeEach(async () => { @@ -37,6 +42,21 @@ describe('Auth', () => { res.body.message.should.be.equal(errorCodes.errorCodes.mail.duplicate.code); }); + it('should fail (register as teacher without teacher email)', async () => { + const teacher = await FixtureUtils.getRandomTeacher(); + const registerUser = teacher; + registerUser.email = 'teacher@student.local'; + + const res = await chai.request(app) + .post(`${BASE_URL}/register`) + .send(registerUser) + .catch(err => err.response); + + res.status.should.be.equal(400); + res.body.name.should.be.equal('BadRequestError'); + res.body.message.should.be.equal(errorCodes.errorCodes.mail.noTeacher.code); + }); + it('should fail (matriculation number is already in use)', async () => { const student = await FixtureUtils.getRandomStudent(); const registerUser = student; @@ -52,18 +72,35 @@ describe('Auth', () => { res.body.message.should.be.equal(errorCodes.errorCodes.duplicateUid.code); }); + it('should pass', async () => { + const registerUser = { uid: '5468907', + firstName: 'firstName', + lastName: 'lastName', + role: 'student', + password: 'test1234', + email: 'local@test.local.de'}; + + const res = await chai.request(app) + .post(`${BASE_URL}/register`) + .send(registerUser) + .catch(err => err.response); + + res.status.should.be.equal(204); + }); + + it('should pass and enroll into course', async () => { - const registerUser: IUser = new User(); - registerUser.uid = '5468907'; - registerUser.profile.firstName = 'firstName'; - registerUser.profile.lastName = 'lastName'; - registerUser.role = 'student'; - registerUser.password = 'test1234'; - registerUser.email = 'local@test.local.de'; + const registerUser = { uid: '5468907', + firstName: 'firstName', + lastName: 'lastName', + role: 'student', + password: 'test1234', + email: 'local@test.local.de'}; + const whitelistUser = await WhitelistUser.create({ uid: registerUser.uid, - firstName: registerUser.profile.firstName, - lastName: registerUser.profile.lastName + firstName: registerUser.firstName, + lastName: registerUser.lastName }); const noElemCourse = await Course.create({ name: 'Test Course 1', @@ -75,29 +112,24 @@ describe('Auth', () => { enrollType: 'whitelist', whitelist: [whitelistUser] }); - return new Promise((resolve, reject) => { - chai.request(app) + const res = await chai.request(app) .post(`${BASE_URL}/register`) .send(registerUser) - .end(async (err, res) => { - res.status.should.be.equal(204); - // Get updated Course. - const resultNoElemCourse = await Course.findById(noElemCourse._id) - .populate('whitelist') - .populate('students'); - const resultElemCourse = await Course.findById(elemCourse._id) - .populate('whitelist') - .populate('students'); - resultNoElemCourse.whitelist.length.should.be.equal(0); - resultNoElemCourse.students.length.should.be.equal(0); - resultElemCourse.whitelist.length.should.be.equal(1); - resultElemCourse.students.length.should.be.equal(1); - resultElemCourse.whitelist[0].uid.should.be.equal(resultElemCourse.students[0].uid); - resultElemCourse.whitelist[0].firstName.should.be.equal(resultElemCourse.students[0].profile.firstName.toLowerCase()); - resultElemCourse.whitelist[0].lastName.should.be.equal(resultElemCourse.students[0].profile.lastName.toLowerCase()); - resolve(); - }); - }); + .catch(err => err.response); + + res.status.should.be.equal(204); + // Get updated Course. + const resultNoElemCourse = await Course.findById(noElemCourse._id) + .populate('whitelist') + .populate('students'); + const resultElemCourse = await Course.findById(elemCourse._id) + .populate('whitelist') + .populate('students'); + resultNoElemCourse.whitelist.length.should.be.equal(0); + resultNoElemCourse.students.length.should.be.equal(0); + resultElemCourse.whitelist.length.should.be.equal(1); + resultElemCourse.students.length.should.be.equal(1); + resultElemCourse.whitelist[0].uid.should.be.equal(resultElemCourse.students[0].uid); }); it('should fail (registration as admin)', async () => { @@ -117,6 +149,100 @@ describe('Auth', () => { }); }) ; + + describe(`POST ${BASE_URL}/activationresend`, () => { + + it('should fail (user not found)', async () => { + const user = await FixtureUtils.getRandomUser(); + const resendActivationUser = user; + resendActivationUser.uid = '99999999'; + + const res = await chai.request(app) + .post(`${BASE_URL}/activationresend`) + .send({'lastname': resendActivationUser.profile.lastName, + 'uid': resendActivationUser.uid, + 'email': resendActivationUser.email }) + .catch(err => err.response); + + res.status.should.be.equal(400); + res.body.name.should.be.equal('BadRequestError'); + res.body.message.should.be.equal(errorCodes.errorCodes.user.userNotFound.code); + }); + + it('should fail (user already activated)', async () => { + const user = await FixtureUtils.getRandomActiveStudent(); + const resendActivationUser = user; + + const res = await chai.request(app) + .post(`${BASE_URL}/activationresend`) + .send({'lastname': resendActivationUser.profile.lastName, + 'uid': resendActivationUser.uid, + 'email': resendActivationUser.email }) + .catch(err => err.response); + + res.status.should.be.equal(400); + res.body.name.should.be.equal('BadRequestError'); + res.body.message.should.be.equal(errorCodes.errorCodes.user.userAlreadyActive.code); + }); + + // reduce timeTillNextActivationResendMin for testing to 15s + config.timeTilNextActivationResendMin = 0.25; + + it('should fail (can only send every ' + config.timeTilNextActivationResendMin + ' min)', async () => { + const student = await FixtureUtils.getRandomInactiveStudent(); + const resendActivationUser = student; + + const res = await chai.request(app) + .post(`${BASE_URL}/activationresend`) + .send({'lastname': resendActivationUser.profile.lastName, + 'uid': resendActivationUser.uid, + 'email': resendActivationUser.email }) + .catch(err => err.response); + + res.status.should.be.equal(503); + res.body.name.should.be.equal('HttpError'); + res.should.have.header('retry-after'); + res.body.message.should.be.equal(errorCodes.errorCodes.user.retryAfter.code); + }); + + it('should fail (email already in use)', async () => { + await delay(Number(config.timeTilNextActivationResendMin) * 60000); + const student = await FixtureUtils.getRandomInactiveStudent(); + const resendActivationUser = student; + const student2 = await FixtureUtils.getRandomActiveStudent(); + const existingUser = student2; + resendActivationUser.email = existingUser.email; + + const res = await chai.request(app) + .post(`${BASE_URL}/activationresend`) + .send({'lastname': resendActivationUser.profile.lastName, + 'uid': resendActivationUser.uid, + 'email': resendActivationUser.email }) + .catch(err => err.response); + + res.status.should.be.equal(400); + res.body.name.should.be.equal('BadRequestError'); + res.body.message.should.be.equal(errorCodes.errorCodes.mail.duplicate.code); + }).timeout(Number(config.timeTilNextActivationResendMin) * 61000); + + it('should pass', async () => { + await delay(Number(config.timeTilNextActivationResendMin) * 60000); + const student = await FixtureUtils.getRandomInactiveStudent(); + const resendActivationUser = student; + + const res = await chai.request(app) + .post(`${BASE_URL}/activationresend`) + .send({'lastname': resendActivationUser.profile.lastName, + 'uid': resendActivationUser.uid, + 'email': resendActivationUser.email }) + .catch(err => err.response); + + res.status.should.be.equal(204); + }).timeout(Number(config.timeTilNextActivationResendMin) * 61000); + + + }) + ; }) ; diff --git a/api/test/integration/course.ts b/api/test/integration/course.ts index e19092c96..cbd45aa53 100644 --- a/api/test/integration/course.ts +++ b/api/test/integration/course.ts @@ -3,7 +3,11 @@ import {Server} from '../../src/server'; import {FixtureLoader} from '../../fixtures/FixtureLoader'; import {JwtUtils} from '../../src/security/JwtUtils'; import {User} from '../../src/models/User'; -import {Course} from '../../src/models/Course'; +import {Course, ICourseModel} from '../../src/models/Course'; +import {ICourse} from '../../../shared/models/ICourse'; +import {ICourseView} from '../../../shared/models/ICourseView'; +import {IUserSubCourseView} from '../../../shared/models/IUserSubCourseView'; +import {IUser} from '../../../shared/models/IUser'; import {FixtureUtils} from '../../fixtures/FixtureUtils'; import chaiHttp = require('chai-http'); @@ -65,6 +69,25 @@ describe('Course', () => { .catch(err => err.response); res.status.should.be.equal(401); }); + + + it('should have a course fixture with "accesskey" enrollType', async () => { + const course = await Course.findOne({enrollType: 'accesskey'}); + should.exist(course); + }); + + it('should not leak access keys to students', async () => { + const student = await FixtureUtils.getRandomStudent(); + + const res = await chai.request(app) + .get(BASE_URL) + .set('Authorization', `JWT ${JwtUtils.generateToken(student)}`); + res.status.should.be.equal(200); + + res.body.forEach((course: any) => { + should.equal(course.accessKey, undefined); + }); + }); }); describe(`POST ${BASE_URL}`, () => { @@ -82,29 +105,96 @@ describe('Course', () => { res.status.should.be.equal(200); res.body.name.should.equal(testData.name); res.body.description.should.equal(testData.description); - }) + }); }); describe(`GET ${BASE_URL} :id`, () => { - it('should get course with given id', async () => { - const teacher = await FixtureUtils.getRandomTeacher(); + async function prepareTestCourse() { + const teachers = await FixtureUtils.getRandomTeachers(2, 2); + const teacher = teachers[0]; + const unauthorizedTeacher = teachers[1]; + const student = await FixtureUtils.getRandomStudent(); const testData = new Course({ name: 'Test Course', description: 'Test description', active: true, - courseAdmin: teacher._id + courseAdmin: teacher, + teachers: [teacher], + enrollType: 'accesskey', + accessKey: 'accessKey1234', + students: [student] }); const savedCourse = await testData.save(); + return {teacher, unauthorizedTeacher, student, testData, savedCourse}; + } + + async function testUnauthorizedGetCourseEdit(savedCourse: ICourseModel, user: IUser) { + const res = await chai.request(app) + .get(`${BASE_URL}/${savedCourse._id}/edit`) + .set('Authorization', `JWT ${JwtUtils.generateToken(user)}`); + + res.should.not.have.status(200); + return res; + } + + function assertUserCourseViewEquality(actual: IUserSubCourseView, expected: IUserSubCourseView) { + actual._id.should.be.equal(expected._id.toString()); + actual.profile.firstName.should.be.equal(expected.profile.firstName); + actual.profile.lastName.should.be.equal(expected.profile.lastName); + actual.email.should.be.equal(expected.email); + } + + it('should get view info for course with given id', async () => { + const {student, testData, savedCourse} = await prepareTestCourse(); const res = await chai.request(app) .get(`${BASE_URL}/${savedCourse._id}`) + .set('Authorization', `JWT ${JwtUtils.generateToken(student)}`); + + res.should.have.status(200); + + const body: ICourseView = res.body; + body.name.should.be.equal(testData.name); + body.description.should.be.equal(testData.description); + assertUserCourseViewEquality(body.courseAdmin, testData.courseAdmin); + for (const [index, actual] of body.teachers.entries()) { + assertUserCourseViewEquality(actual, testData.teachers[index]); + } + + should.equal(res.body.accessKey, undefined); + }); + + it('should get edit info for course with given id', async () => { + const {teacher, testData, savedCourse} = await prepareTestCourse(); + + const res = await chai.request(app) + .get(`${BASE_URL}/${savedCourse._id}/edit`) .set('Authorization', `JWT ${JwtUtils.generateToken(teacher)}`); res.should.have.status(200); - res.body.name.should.be.equal(testData.name); - res.body.description.should.be.equal(testData.description); - res.body.active.should.be.equal(testData.active); + + const body: ICourse = res.body; + body.name.should.be.equal(testData.name); + body.description.should.be.equal(testData.description); + body.active.should.be.equal(testData.active); + body.enrollType.should.be.equal(testData.enrollType); + body.accessKey.should.be.equal(testData.accessKey); + }); + + it('should not get edit info for course as student', async () => { + const {savedCourse, student} = await prepareTestCourse(); + const res = await testUnauthorizedGetCourseEdit(savedCourse, student); + res.body.name.should.be.equal('AccessDeniedError'); + res.body.should.have.property('message'); + res.body.should.have.property('stack'); + }); + + it('should not get edit info for course as unauthorized teacher', async () => { + const {savedCourse, unauthorizedTeacher} = await prepareTestCourse(); + const res = await testUnauthorizedGetCourseEdit(savedCourse, unauthorizedTeacher); + res.body.name.should.be.oneOf(['NotFoundError', 'ForbiddenError']); + res.body.should.have.property('stack'); }); it('should not get course not a teacher of course', async () => { @@ -146,11 +236,19 @@ describe('Course', () => { const savedCourse = await testData.save(); testDataUpdate._id = savedCourse._id; - const res = await chai.request(app) + let res = await chai.request(app) .put(`${BASE_URL}/${testDataUpdate._id}`) .set('Authorization', `JWT ${JwtUtils.generateToken(teacher)}`) .send(testDataUpdate); + res.should.have.status(200); + res.body.name.should.be.eq(testDataUpdate.name); + res.body._id.should.be.eq(testDataUpdate.id); + + res = await chai.request(app) + .get(`${BASE_URL}/${res.body._id}/edit`) + .set('Authorization', `JWT ${JwtUtils.generateToken(teacher)}`); + res.should.have.status(200); res.body.name.should.be.eq(testDataUpdate.name); res.body.description.should.be.eq(testDataUpdate.description); @@ -219,9 +317,3 @@ describe('Course', () => { }); }); }); - - - - - - diff --git a/api/test/integration/unit/codeKataUnit.ts b/api/test/integration/unit/codeKataUnit.ts index 499f8d063..10b5fab67 100644 --- a/api/test/integration/unit/codeKataUnit.ts +++ b/api/test/integration/unit/codeKataUnit.ts @@ -117,6 +117,8 @@ describe(`CodeKataUnit ${BASE_URL}`, () => { res.status.should.be.equal(200); res.body.name.should.equal(model.name); res.body.description.should.equal(model.description); + res.body.unitCreator.profile.lastName.should.equal(courseAdmin.profile.lastName); + res.body.unitCreator.profile.firstName.should.equal(courseAdmin.profile.firstName); }); it('should update a codeKata', async () => { diff --git a/api/test/integration/user.ts b/api/test/integration/user.ts index dd92780da..db46db926 100644 --- a/api/test/integration/user.ts +++ b/api/test/integration/user.ts @@ -1,8 +1,10 @@ import * as chai from 'chai'; +import * as request from 'superagent'; import {Server} from '../../src/server'; import {FixtureLoader} from '../../fixtures/FixtureLoader'; import {JwtUtils} from '../../src/security/JwtUtils'; import {User} from '../../src/models/User'; +import {errorCodes} from '../../src/config/errorCodes'; import {FixtureUtils} from '../../fixtures/FixtureUtils'; import {IUser} from '../../../shared/models/IUser'; import chaiHttp = require('chai-http'); @@ -32,7 +34,7 @@ describe('User', () => { res.status.should.be.equal(200); res.body.should.be.a('array'); - res.body.length.should.be.equal(40); + res.body.length.should.be.equal(42); }); it('should fail with wrong authorization', async () => { @@ -45,7 +47,7 @@ describe('User', () => { res.status.should.be.equal(401); }); - it('should return the a user object', async () => { + it('should return the requested user object', async () => { const admin = await FixtureUtils.getRandomAdmin(); const res = await chai.request(app) @@ -154,120 +156,76 @@ describe('User', () => { }); describe(`PUT ${BASE_URL}`, () => { + function requestUserUpdate(currentUser: IUser, updatedUser: IUser) { + return chai.request(app) + .put(`${BASE_URL}/${updatedUser._id}`) + .set('Authorization', `JWT ${JwtUtils.generateToken(currentUser)}`) + .send(updatedUser); + } + + function requestUserUpdateAndCatch(currentUser: IUser, updatedUser: IUser) { + return requestUserUpdate(currentUser, updatedUser).catch(err => err.response); + } + + function assertFailure(res: request.Response, status: number, name: string, message: string) { + res.status.should.be.equal(status); + res.body.name.should.be.equal(name); + res.body.message.should.be.equal(message); + } + it('should fail with bad request (revoke own admin privileges)', async () => { const admin = await FixtureUtils.getRandomAdmin(); - const updatedUser = admin; updatedUser.role = 'teacher'; - const res = await chai.request(app) - .put(`${BASE_URL}/${admin._id}`) - .set('Authorization', `JWT ${JwtUtils.generateToken(admin)}`) - .send(updatedUser) - .catch(err => err.response); - res.status.should.be.equal(400); - res.body.name.should.be.equal('BadRequestError'); - res.body.message.should.be.equal('You can\'t revoke your own privileges'); - }); - - it('should fail with wrong authorization (uid)', (done) => { - User.findOne({email: 'teacher1@test.local'}) - .then((user) => { - const updatedUser = user; - updatedUser.uid = '987456'; - chai.request(app) - .put(`${BASE_URL}/${user._id}`) - .set('Authorization', `JWT ${JwtUtils.generateToken(user)}`) - .send(updatedUser) - .end((err, res) => { - res.status.should.be.equal(403); - res.body.name.should.be.equal('ForbiddenError'); - res.body.message.should.be.equal('Only users with admin privileges can change uids'); - done(); - }); - }) - .catch(done); + const res = await requestUserUpdateAndCatch(admin, updatedUser); + assertFailure(res, 400, 'BadRequestError', errorCodes.user.cantChangeOwnRole.text); }); it('should fail with bad request (email already in use)', async () => { - const users = await FixtureUtils.getRandomUsers(2, 2); - const updatedUser = users[0]; - updatedUser.email = users[1].email; - - const res = await chai.request(app) - .put(`${BASE_URL}/${users[0]._id}`) - .set('Authorization', `JWT ${JwtUtils.generateToken(users[0])}`) - .send(updatedUser) - .catch(err => err.response); + const admin = await FixtureUtils.getRandomAdmin(); + const updatedUser = await FixtureUtils.getRandomStudent(); + updatedUser.email = admin.email; - res.status.should.be.equal(400); - res.body.name.should.be.equal('BadRequestError'); - res.body.message.should.be.equal('This mail address is already in use.'); + const res = await requestUserUpdateAndCatch(admin, updatedUser); + assertFailure(res, 400, 'BadRequestError', errorCodes.user.emailAlreadyInUse.text); }); - it('should fail with wrong authorization (role edit)', async () => { + // This test is disabled because there currently is no role beneath 'admin' that is allowed to edit other users. + // Reactivate and adjust this test if such a role should become available in the future. + // (Previously teachers had permission to change some parts of any student's profile.) + /* + it('should fail changing other user\'s uid with wrong authorization (not admin)', async () => { const teacher = await FixtureUtils.getRandomTeacher(); - const updatedUser = teacher; - updatedUser.role = 'admin'; - - const res = await chai.request(app) - .put(`${BASE_URL}/${teacher._id}`) - .set('Authorization', `JWT ${JwtUtils.generateToken(teacher)}`) - .send(updatedUser) - .catch(err => err.response); + const updatedUser = await FixtureUtils.getRandomStudent(); + updatedUser.uid = '987456'; - res.status.should.be.equal(403); - res.body.name.should.be.equal('ForbiddenError'); - res.body.message.should.be.equal('Only users with admin privileges can change roles'); + const res = await requestUserUpdateAndCatch(teacher, updatedUser); + assertFailure(res, 403, 'ForbiddenError', errorCodes.user.onlyAdminsCanChangeUids.text); }); + */ - it('should fail with wrong authorization (uid)', async () => { - const teacher = await FixtureUtils.getRandomTeacher(); - const updatedUser = teacher; - updatedUser.uid = '987456'; - - const res = await chai.request(app) - .put(`${BASE_URL}/${teacher._id}`) - .set('Authorization', `JWT ${JwtUtils.generateToken(teacher)}`) - .send(updatedUser) - .catch(err => err.response); + it('should fail changing other user\'s name with wrong authorization (low edit level)', async () => { + const [student, updatedUser] = await FixtureUtils.getRandomStudents(2, 2); + updatedUser.profile.firstName = 'TEST'; - res.status.should.be.equal(403); - res.body.name.should.be.equal('ForbiddenError'); - res.body.message.should.be.equal('Only users with admin privileges can change uids'); + const res = await requestUserUpdateAndCatch(student, updatedUser); + assertFailure(res, 403, 'ForbiddenError', errorCodes.user.cantChangeUserWithHigherRole.text); }); it('should update user base data without password', async () => { - const student = await FixtureUtils.getRandomStudent(); - const updatedUser = student; - updatedUser.password = undefined; - updatedUser.profile.firstName = 'Updated'; - updatedUser.profile.lastName = 'User'; - updatedUser.email = 'student2@updated.local'; - const res = await chai.request(app) - .put(`${BASE_URL}/${student._id}`) - .set('Authorization', `JWT ${JwtUtils.generateToken(student)}`) - .send(updatedUser); - res.status.should.be.equal(200); - res.body.profile.firstName.should.be.equal('Updated'); - res.body.profile.lastName.should.be.equal('User'); - res.body.email.should.be.equal('student2@updated.local'); - }); - - it('should fail with missing password', async () => { const student = await FixtureUtils.getRandomStudent(); const updatedUser = student; - updatedUser.password = '1234test'; - - const res = await chai.request(app) - .put(`${BASE_URL}/${student._id}`) - .set('Authorization', `JWT ${JwtUtils.generateToken(student)}`) - .send(updatedUser) - .catch(err => err.response); + updatedUser.password = undefined; + updatedUser.profile.firstName = 'Updated'; + updatedUser.profile.lastName = 'User'; + updatedUser.email = 'student2@updated.local'; - res.status.should.be.equal(400); - res.body.name.should.be.equal('BadRequestError'); - res.body.message.should.be.equal('Invalid Current Password!'); + const res = await requestUserUpdate(student, updatedUser); + res.status.should.be.equal(200); + res.body.profile.firstName.should.be.equal('Updated'); + res.body.profile.lastName.should.be.equal('User'); + res.body.email.should.be.equal('student2@updated.local'); }); it('should update user data', async () => { @@ -278,11 +236,7 @@ describe('User', () => { updatedUser.profile.lastName = 'User'; updatedUser.email = 'student1@updated.local'; - const res = await chai.request(app) - .put(`${BASE_URL}/${student._id}`) - .set('Authorization', `JWT ${JwtUtils.generateToken(student)}`) - .send(updatedUser); - + const res = await requestUserUpdate(student, updatedUser); res.status.should.be.equal(200); res.body.profile.firstName.should.be.equal('Updated'); res.body.profile.lastName.should.be.equal('User'); @@ -297,11 +251,7 @@ describe('User', () => { updatedUser.profile.lastName = 'User'; updatedUser.email = 'student@updated.local'; - const res = await chai.request(app) - .put(`${BASE_URL}/${student._id}`) - .set('Authorization', `JWT ${JwtUtils.generateToken(student)}`) - .send(updatedUser); - + const res = await requestUserUpdate(student, updatedUser); res.status.should.be.equal(200); res.body.profile.firstName.should.be.equal('Updated'); res.body.profile.lastName.should.be.equal('User'); @@ -319,11 +269,7 @@ describe('User', () => { updatedUser.profile.lastName = 'User'; updatedUser.email = 'student@updated.local'; - const res = await chai.request(app) - .put(`${BASE_URL}/${student._id}`) - .set('Authorization', `JWT ${JwtUtils.generateToken(admin)}`) - .send(updatedUser); - + const res = await requestUserUpdate(admin, updatedUser); res.status.should.be.equal(200); res.body.uid.should.be.equal(origUid); res.body.profile.firstName.should.be.equal('Updated'); @@ -333,22 +279,63 @@ describe('User', () => { }); describe(`POST ${BASE_URL}/picture`, () => { + async function requestAddUserPicture(currentUser: IUser, targetUser: IUser) { + return await chai.request(app) + .post(`${BASE_URL}/picture/${targetUser._id}`) + .set('Authorization', `JWT ${JwtUtils.generateToken(currentUser)}`) + .attach('file', fs.readFileSync('test/resources/test.png'), 'test.png'); + } + + function assertSuccess(res: request.Response) { + res.status.should.be.equal(200); + res.body.profile.picture.should.be.an('object'); + res.body.profile.picture.should.have.all.keys('alias', 'name', 'path'); + res.body.profile.picture.alias.should.be.equal('test.png'); + } + it('should upload a new user picture', async () => { const admin = await FixtureUtils.getRandomAdmin(); + const res = await requestAddUserPicture(admin, admin); + assertSuccess(res); + }); + + it('should fail to upload a new picture for another user (as student)', async () => { + const [student, targetUser] = await FixtureUtils.getRandomStudents(2, 2); + const res = await requestAddUserPicture(student, targetUser); + res.status.should.be.equal(403); + res.body.name.should.be.equal('ForbiddenError'); + res.body.message.should.be.equal(errorCodes.user.cantChangeUserWithHigherRole.text); + }); + + it('should upload a new picture for another user (as admin)', async () => { + const admin = await FixtureUtils.getRandomAdmin(); + const targetUser = await FixtureUtils.getRandomStudent(); + const res = await requestAddUserPicture(admin, targetUser); + assertSuccess(res); + }); + + it('should block non images when uploading new user picture', async () => { + const admin = await FixtureUtils.getRandomAdmin(); const res = await chai.request(app) .post(`${BASE_URL}/picture/${admin._id}`) .set('Authorization', `JWT ${JwtUtils.generateToken(admin)}`) - .attach('file', fs.readFileSync('test/resources/test.png'), 'test.png'); + .attach('file', fs.readFileSync('test/resources/wrong-format.rtf'), 'wrong-format.txt'); - res.status.should.be.equal(200); - res.body.profile.picture.name.should.be.equal('test.png'); + res.status.should.be.equal(403); + res.body.name.should.be.equal('ForbiddenError'); }); }); describe(`DELETE ${BASE_URL}`, () => { + async function ensureOnlyOneAdmin() { + const admins = await FixtureUtils.getRandomAdmins(1, 2); + admins.length.should.be.eq(1); + return admins[0]; + } + it('should fail to delete the only admin', async () => { - const admin = await FixtureUtils.getRandomAdmin(); + const admin = await ensureOnlyOneAdmin(); const res = await chai.request(app) .del(`${BASE_URL}/${admin._id}`) @@ -357,7 +344,30 @@ describe('User', () => { res.status.should.be.equal(400); res.body.name.should.be.equal('BadRequestError'); - res.body.message.should.be.equal('There are no other users with admin privileges.'); + res.body.message.should.be.equal(errorCodes.user.noOtherAdmins.text); + }); + + it('should (promote a teacher to admin and) let the old admin delete itself', async () => { + const admin = await ensureOnlyOneAdmin(); + const promotedUser = await FixtureUtils.getRandomTeacher(); + { // Promote the teacher to admin + promotedUser.role = 'admin'; + + const res = await chai.request(app) + .put(`${BASE_URL}/${promotedUser._id}`) + .set('Authorization', `JWT ${JwtUtils.generateToken(admin)}`) + .send(promotedUser); + + res.status.should.be.equal(200); + res.body.role.should.be.equal('admin'); + } + { // Delete the old admin + const res = await chai.request(app) + .del(`${BASE_URL}/${admin._id}`) + .set('Authorization', `JWT ${JwtUtils.generateToken(admin)}`); + + res.status.should.be.equal(200); + } }); it('should fail to delete (wrong role)', async () => { diff --git a/api/test/integration/whitelistUser.ts b/api/test/integration/whitelistUser.ts index 623b71b2f..1cb980202 100644 --- a/api/test/integration/whitelistUser.ts +++ b/api/test/integration/whitelistUser.ts @@ -105,7 +105,7 @@ describe('Whitelist User', () => { addedUsers[0].uid.should.be.eq(whitelistUser.uid); addedUsers[0].profile.firstName.should.be.eq(whitelistUser.firstName); addedUsers[0].profile.lastName.should.be.eq(whitelistUser.lastName); - }) + }); }); describe(`PUT ${BASE_URL}`, () => { @@ -204,6 +204,6 @@ describe('Whitelist User', () => { const resCourse = await Course.findById(course._id).populate('students'); const emptyUsers: IUser[] = resCourse.students.filter(stud => stud.uid === member.uid); emptyUsers.length.should.be.eq(0); - }) + }); }); }); diff --git a/api/test/mocha.env.js b/api/test/mocha.env.js index e86b147f0..225be9b28 100644 --- a/api/test/mocha.env.js +++ b/api/test/mocha.env.js @@ -1,2 +1,3 @@ process.env.DB_NAME = 'test'; process.env.NODE_ENV = 'test'; +process.env.TEACHER_MAIL_REGEX = '(.+)@teacher\\.local'; diff --git a/api/test/mocha.opts b/api/test/mocha.opts index 0d666346f..7542cd1bd 100644 --- a/api/test/mocha.opts +++ b/api/test/mocha.opts @@ -3,3 +3,4 @@ build/test/**/*.js --reporter spec --require test/mocha.env.js --timeout 10000 +--exit diff --git a/api/test/resources/wrong-format.rtf b/api/test/resources/wrong-format.rtf new file mode 100644 index 000000000..ea3aad0cd --- /dev/null +++ b/api/test/resources/wrong-format.rtf @@ -0,0 +1,8 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1561\cocoasubrtf400 +{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +{\*\expandedcolortbl;;} +\paperw11900\paperh16840\margl1440\margr1440\vieww10800\viewh8400\viewkind0 +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural\partightenfactor0 + +\f0\fs24 \cf0 Test} \ No newline at end of file diff --git a/api/test/unit/utilities.ts b/api/test/unit/utilities.ts new file mode 100644 index 000000000..7448b30b6 --- /dev/null +++ b/api/test/unit/utilities.ts @@ -0,0 +1,107 @@ +import {expect} from 'chai'; + +import Pick from '../../src/utilities/Pick'; +import {IProperties} from '../../../shared/models/IProperties'; + +import {extractMongoId} from '../../src/utilities/ExtractMongoId'; +import {Types as mongooseTypes} from 'mongoose'; + +import {ensureMongoToObject} from '../../src/utilities/EnsureMongoToObject'; +import {DocumentToObjectOptions} from 'mongoose'; +import {Course, ICourseModel} from '../../src/models/Course'; +import {ICourse} from '../../../shared/models/ICourse'; +import {FixtureLoader} from '../../fixtures/FixtureLoader'; + +const fixtureLoader = new FixtureLoader(); + +describe('Testing utilities', () => { + describe('Pick', () => { + let input: IProperties; + + beforeEach(function() { + input = {a: 0, b: 'b', c: [1, 2, 3], d: {e: 'f'}, e: {d: 'c'}}; + }); + + it('should pick only certain attributes', () => { + const result: IProperties = Pick.only(['a', 'c'], input); + expect(result).to.eql({a: 0, c: [1, 2, 3]}); + }); + + it('should pick certain attributes as empty containers', () => { + const result: IProperties = Pick.asEmpty(['a', 'c', 'd'], input); + expect(result).to.eql({c: [], d: {}}); + }); + }); + + describe('ExtractMongoId', () => { + const idAsObjectId = mongooseTypes.ObjectId(); + const idDirect = {id: idAsObjectId.toHexString()}; + const idString = new String(idDirect.id); // tslint:disable-line + const idExpect = idDirect.id; + const idArray = [idAsObjectId, idDirect, {}, idAsObjectId, idString, 1, idExpect, idDirect]; + const fallback = 'fallback'; + + it('should extract an id from an ObjectID object', () => { + expect(extractMongoId(idAsObjectId)).to.eq(idExpect); + }); + + it('should extract an id from an object with "id" property', () => { + expect(extractMongoId(idDirect)).to.eq(idExpect); + }); + + it('should return an id String object as string', () => { + expect(extractMongoId(idString)).to.eq(idExpect); + }); + + it('should return an id string unmodified', () => { + expect(extractMongoId(idExpect)).to.eq(idExpect); + }); + + it('should yield undefined for invalid input', () => { + expect(extractMongoId({})).to.eq(undefined); + expect(extractMongoId(1)).to.eq(undefined); + }); + + it('should return a specified fallback for invalid input', () => { + expect(extractMongoId({}, fallback)).to.eq(fallback); + expect(extractMongoId(1, fallback)).to.eq(fallback); + }); + + it('should only extract ids for valid objects in an array', () => { + expect(extractMongoId(idArray)).to.eql([idExpect, idExpect, idExpect, idExpect, idExpect, idExpect]); + }); + + it('should extract ids for valid objects or return fallback values in an array', () => { + expect(extractMongoId(idArray, 'fallback')).to.eql([idExpect, idExpect, fallback, idExpect, idExpect, fallback, idExpect, idExpect]); + }); + }); + + describe('EnsureMongoToObject', () => { + // Before each test we reset the database + beforeEach(async () => { + await fixtureLoader.load(); + }); + + it('should return the (ICourse) object without modification', async () => { + const course: ICourse = (await Course.findOne()).toObject(); + expect(ensureMongoToObject(course)).to.eql(course); + }); + + it('should call the mongoose (ICourseModel) toObject function and return the result', async () => { + const course = await Course.findOne(); + expect(ensureMongoToObject(course)).to.eql(course.toObject()); + }); + + it('should call the mongoose (ICourseModel) toObject function with a transform option and return the result', async () => { + const course = await Course.findOne(); + const options: DocumentToObjectOptions = { + transform: (doc: ICourseModel, ret: any) => { + ret._id = doc._id.toString() + '-transform-test'; + } + }; + const expectedResult = course.toObject(options); + expect(expectedResult._id).to.eq(course._id.toString() + '-transform-test'); + expect(ensureMongoToObject(course, options)).to.eql(expectedResult); + }); + }); +}); diff --git a/app/webFrontend/karma.conf.js b/app/webFrontend/karma.conf.js index 84b4cd5ac..af139fada 100644 --- a/app/webFrontend/karma.conf.js +++ b/app/webFrontend/karma.conf.js @@ -1,5 +1,5 @@ // Karma configuration file, see link for more information -// https://karma-runner.github.io/0.13/config/configuration-file.html +// https://karma-runner.github.io/1.0/config/configuration-file.html module.exports = function (config) { config.set({ @@ -15,15 +15,6 @@ module.exports = function (config) { client:{ clearContext: false // leave Jasmine Spec Runner output visible in browser }, - files: [ - { pattern: './src/test.ts', watched: false } - ], - preprocessors: { - './src/test.ts': ['@angular/cli'] - }, - mime: { - 'text/x-typescript': ['ts','tsx'] - }, coverageIstanbulReporter: { reports: [ 'html', 'lcovonly' ], fixWebpackSourcePaths: true @@ -31,9 +22,7 @@ module.exports = function (config) { angularCli: { environment: 'dev' }, - reporters: config.angularCli && config.angularCli.codeCoverage - ? ['progress', 'coverage-istanbul'] - : ['progress', 'kjhtml'], + reporters: ['progress', 'kjhtml'], port: 9876, colors: true, logLevel: config.LOG_INFO, diff --git a/app/webFrontend/package-lock.json b/app/webFrontend/package-lock.json index b000e5825..a3ab8c2d6 100644 --- a/app/webFrontend/package-lock.json +++ b/app/webFrontend/package-lock.json @@ -5,9 +5,9 @@ "requires": true, "dependencies": { "@angular-devkit/build-optimizer": { - "version": "0.0.35", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.0.35.tgz", - "integrity": "sha512-7JxZZAYFSCc0tP6+NrRn3b2Cd1b9d+a3+OfwVNyNsNd2unelqUMko2hm0KLbC8BXcXt/OILg1E/ZgLAXSS47nw==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.3.2.tgz", + "integrity": "sha512-U0BCZtThq5rUfY08shHXpxe8ZhSsiYB/cJjUvAWRTs/ORrs8pbngS6xwseQws8d/vHoVrtqGD9GU9h8AmFRERQ==", "dev": true, "requires": { "loader-utils": "1.1.0", @@ -25,209 +25,317 @@ } }, "@angular-devkit/core": { - "version": "0.0.22", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-0.0.22.tgz", - "integrity": "sha512-zxrNtTiv60liye/GGeRMnnGgLgAWoqlMTfPLMW0D1qJ4bbrPHtme010mpxS3QL4edcDtQseyXSFCnEkuo2MrRw==", - "dev": true, + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-0.4.9.tgz", + "integrity": "sha512-MOi8F6kiu9GKVzItO0NV0hPcjK/XfbeaMkBTewC/CWZKnNGeBmc3YJyBMRDaZXr5AxhzzxDDpQAso5oYJ2qXSw==", "requires": { + "ajv": "5.5.2", + "chokidar": "1.7.0", + "rxjs": "6.0.0-uncanny-rc.7", "source-map": "0.5.7" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "rxjs": { + "version": "6.0.0-uncanny-rc.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.0.0-uncanny-rc.7.tgz", + "integrity": "sha512-mXBJnSpbrotKF83b1sd5uSa7q/J/y99yBArB02l6B1v2QAP18FCn2BwRXfC9O4A+75mfwUAIUWJyLilboF5z2A==", + "requires": { + "tslib": "1.9.0" + } + }, + "tslib": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz", + "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==" + } } }, "@angular-devkit/schematics": { - "version": "0.0.40", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-0.0.40.tgz", - "integrity": "sha512-VX5Rw0jrAIDouo8JrBz4pwCL7J9QDFiVK2ZCiYHXMsMqKo0+m7Dv6qdQAkhm37T/UOxU1hT8gdQ0l9nHYKVeAQ==", + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-0.4.9.tgz", + "integrity": "sha512-hRz2l0hX/sUMY7X5wJz6zGP4O8VOWwbdxBel/WbDGpiq/1IljfFZlh8L78k4tczL0cT+dkeMqzrh/TLvF48wNQ==", "dev": true, "requires": { - "@angular-devkit/core": "0.0.22", "@ngtools/json-schema": "1.1.0", - "@schematics/schematics": "0.0.10", - "minimist": "1.2.0", - "rxjs": "5.5.5" + "rxjs": "6.0.0-uncanny-rc.7" + }, + "dependencies": { + "rxjs": { + "version": "6.0.0-uncanny-rc.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.0.0-uncanny-rc.7.tgz", + "integrity": "sha512-mXBJnSpbrotKF83b1sd5uSa7q/J/y99yBArB02l6B1v2QAP18FCn2BwRXfC9O4A+75mfwUAIUWJyLilboF5z2A==", + "dev": true, + "requires": { + "tslib": "1.9.0" + } + }, + "tslib": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz", + "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==", + "dev": true + } } }, "@angular/animations": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-5.1.0.tgz", - "integrity": "sha512-s0tV6y2D16CQAcXjv8CN8AahHb+LoWm9KAUkxvSJ18ZZQweuAY4T8jlRB95ODRFFKfjwyRD9HqXKUC5yHmG9ww==", + "version": "5.2.10", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-5.2.10.tgz", + "integrity": "sha512-QNYXqnti8BeFriNaZ/juLnO6l0MVlVNUmLycC9ma+pdTiEJl8rtgZ0WXxgOCjScyKpInkWn2J+m9FI/78SYFpw==", "requires": { "tslib": "1.8.0" } }, "@angular/cdk": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-5.0.0.tgz", - "integrity": "sha512-+u67Bns23tuCUGUCWhqkR/+onCwB4ObRURUv7ar2+BHw5VIvzML+IOCi1BJRF7gqvL+IVYQpLuY2cQh0J2SbBQ==", + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-5.2.5.tgz", + "integrity": "sha512-GN8m1d+VcCE9+Bgwv06Y8YJKyZ0i9ZIq2ZPBcJYt+KVgnVVRg4JkyUNxud07LNsvzOX22DquHqmIZiC4hAG7Ag==", "requires": { "tslib": "1.8.0" } }, "@angular/cli": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-1.6.0.tgz", - "integrity": "sha512-X049QAgSKy5J48byyo3T6iBTHubTC66QBMshMpTT7PWAaSq3HpPPE1xW0WwgFIXZWMQIsmncaqPwmnFmxljUdw==", - "dev": true, - "requires": { - "@angular-devkit/build-optimizer": "0.0.35", - "@angular-devkit/schematics": "0.0.40", - "@ngtools/json-schema": "1.1.0", - "@ngtools/webpack": "1.9.0", - "@schematics/angular": "0.1.10", - "autoprefixer": "6.7.7", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-1.7.3.tgz", + "integrity": "sha512-19sh0SbjneG7/R/FvZBfHsHqfIqyj4LQuXdddJKMCDM97UoHQTjfgrpRvBf3a3lR79wdLXchWJBD9Yc6ifosEA==", + "dev": true, + "requires": { + "@angular-devkit/build-optimizer": "0.3.2", + "@angular-devkit/core": "0.3.2", + "@angular-devkit/schematics": "0.3.2", + "@ngtools/json-schema": "1.2.0", + "@ngtools/webpack": "1.10.2", + "@schematics/angular": "0.3.2", + "@schematics/package-update": "0.3.2", + "ajv": "6.3.0", + "autoprefixer": "7.2.6", + "cache-loader": "1.2.2", "chalk": "2.2.2", - "circular-dependency-plugin": "4.3.0", - "common-tags": "1.5.1", - "copy-webpack-plugin": "4.2.3", + "circular-dependency-plugin": "4.4.0", + "clean-css": "4.1.11", + "common-tags": "1.7.2", + "copy-webpack-plugin": "4.4.3", "core-object": "3.1.5", - "css-loader": "0.28.7", - "cssnano": "3.10.0", "denodeify": "1.2.1", "ember-cli-string-utils": "1.1.0", - "exports-loader": "0.6.4", "extract-text-webpack-plugin": "3.0.2", - "file-loader": "1.1.5", + "file-loader": "1.1.11", "fs-extra": "4.0.3", "glob": "7.1.2", "html-webpack-plugin": "2.30.1", - "istanbul-instrumenter-loader": "2.0.0", + "istanbul-instrumenter-loader": "3.0.0", "karma-source-map-support": "1.2.0", "less": "2.7.3", - "less-loader": "4.0.5", - "license-webpack-plugin": "1.1.1", + "less-loader": "4.1.0", + "license-webpack-plugin": "1.3.1", + "loader-utils": "1.1.0", "lodash": "4.17.4", "memory-fs": "0.4.1", "minimatch": "3.0.4", "node-modules-path": "1.0.1", - "node-sass": "4.7.2", + "node-sass": "4.9.0", "nopt": "4.0.1", "opn": "5.1.0", "portfinder": "1.0.13", - "postcss-custom-properties": "6.2.0", - "postcss-loader": "2.0.9", - "postcss-url": "7.3.0", + "postcss": "6.0.21", + "postcss-import": "11.1.0", + "postcss-loader": "2.1.3", + "postcss-url": "7.3.1", "raw-loader": "0.5.1", "resolve": "1.5.0", - "rxjs": "5.5.5", - "sass-loader": "6.0.6", + "rxjs": "5.5.7", + "sass-loader": "6.0.7", "semver": "5.4.1", "silent-error": "1.1.0", - "source-map-loader": "0.2.3", "source-map-support": "0.4.18", - "style-loader": "0.13.2", + "style-loader": "0.19.1", "stylus": "0.54.5", - "stylus-loader": "3.0.1", - "uglifyjs-webpack-plugin": "1.1.2", + "stylus-loader": "3.0.2", + "uglifyjs-webpack-plugin": "1.2.4", "url-loader": "0.6.2", - "webpack": "3.10.0", - "webpack-concat-plugin": "1.4.2", + "webpack": "3.11.0", "webpack-dev-middleware": "1.12.2", - "webpack-dev-server": "2.9.7", - "webpack-merge": "4.1.1", + "webpack-dev-server": "2.11.2", + "webpack-merge": "4.1.2", "webpack-sources": "1.1.0", - "webpack-subresource-integrity": "1.0.3", - "zone.js": "0.8.18" + "webpack-subresource-integrity": "1.0.4" }, "dependencies": { "@angular-devkit/core": { - "version": "0.0.22", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-0.0.22.tgz", - "integrity": "sha512-zxrNtTiv60liye/GGeRMnnGgLgAWoqlMTfPLMW0D1qJ4bbrPHtme010mpxS3QL4edcDtQseyXSFCnEkuo2MrRw==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-0.3.2.tgz", + "integrity": "sha512-zABk/iP7YX5SVbmK4e+IX7j2d0D37MQJQiKgWdV3JzfvVJhNJzddiirtT980pIafoq+KyvTgVwXtc+vnux0oeQ==", "dev": true, "requires": { + "ajv": "5.5.2", + "chokidar": "1.7.0", + "rxjs": "5.5.7", "source-map": "0.5.7" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + } + } + }, + "@angular-devkit/schematics": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-0.3.2.tgz", + "integrity": "sha512-B6zZoqvHaTJy+vVdA6EtlxnCdGMa5elCa4j9lQLC3JI8DLvMXUWkCIPVbPzJ/GSRR9nsKWpvYMYaJyfBDUqfhw==", + "dev": true, + "requires": { + "@ngtools/json-schema": "1.2.0", + "rxjs": "5.5.7" } }, + "@ngtools/json-schema": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ngtools/json-schema/-/json-schema-1.2.0.tgz", + "integrity": "sha512-pMh+HDc6mOjUO3agRfB1tInimo7hf67u+0Cska2bfXFe6oU7rSMnr5PLVtiZVgwMoBHpx/6XjBymvcnWPo2Uzg==", + "dev": true + }, "@schematics/angular": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-0.1.10.tgz", - "integrity": "sha512-ykq4FL0WTygkpvIcGDxnxHHT2uvJMWseDeAujmfyZpzdT9X22GOTURNo3LjvOIhhVUpMVZvnAYqjV46KqB702g==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-0.3.2.tgz", + "integrity": "sha512-Elrk0BA951s0ScFZU0AWrpUeJBYVR52DZ1QTIO5R0AhwEd1PW4olI8szPLGQlVW5Sd6H0FA/fyFLIvn2r9v6Rw==", + "dev": true, + "requires": { + "typescript": "2.6.2" + } + }, + "@schematics/package-update": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@schematics/package-update/-/package-update-0.3.2.tgz", + "integrity": "sha512-7aVP4994Hu8vRdTTohXkfGWEwLhrdNP3EZnWyBootm5zshWqlQojUGweZe5zwewsKcixeVOiy2YtW+aI4aGSLA==", + "dev": true, + "requires": { + "rxjs": "5.5.7", + "semver": "5.4.1", + "semver-intersect": "1.3.1" + } + }, + "rxjs": { + "version": "5.5.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.7.tgz", + "integrity": "sha512-Hxo2ac8gRQjwjtKgukMIwBRbq5+KAeEV5hXM4obYBOAghev41bDQWgFH4svYiU9UnQ5kNww2LgfyBdevCd2HXA==", "dev": true, "requires": { - "@angular-devkit/core": "0.0.22" + "symbol-observable": "1.0.1" } + }, + "symbol-observable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", + "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", + "dev": true + }, + "typescript": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.6.2.tgz", + "integrity": "sha1-PFtv1/beCRQmkCfwPAlGdY92c6Q=", + "dev": true } } }, "@angular/common": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-5.1.0.tgz", - "integrity": "sha512-J6E0OfTJJGcyoKU51ZucsDFV40YEAPgP6VCIPYECgOFHxrqg6O1ZFZSD1fdviMXMLVEFCi6Fy6IB7GJyiWgDIA==", + "version": "5.2.10", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-5.2.10.tgz", + "integrity": "sha512-4zgI/Q6bo/KCvrDPf8gc2IpTJ3PFKgd9RF4jZuh1uc+uEYTAj396tDF8o412AJ/iwtYOHWUx+YgzAvT8dHXZ5Q==", "requires": { "tslib": "1.8.0" } }, "@angular/compiler": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-5.1.0.tgz", - "integrity": "sha512-iyFQqmhKNRSc9JRx7ty6z/wCsypjpbRu0QR6q2LMa6imuCt9qLHOvTajBQExRB8guqd/LTVDG4WiYY1lf8iO2w==", + "version": "5.2.10", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-5.2.10.tgz", + "integrity": "sha512-FI9ip+aWGpKQB+VfNbFQ+wyh0K4Th8Q/MrHxW6CN4BYVAfFtfORRohvyyYk0sRxuQO8JFN3W/FFfdXjuL+cZKw==", "requires": { "tslib": "1.8.0" } }, "@angular/compiler-cli": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-5.1.0.tgz", - "integrity": "sha512-M1//TjgcckkwTMeGTRe7mvFY+00NxaLqlsObnGA9+R3T9cpWeLpy5iVD444Wdxl5MA/Bo3TgGNmeXZsJvh466w==", + "version": "5.2.10", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-5.2.10.tgz", + "integrity": "sha512-RhI26rVALRn3LrU0CAIEj56m60vLyCd8e2Ah79yRP6vlXL8k6SylXytUljTeXIBtiVu2Bi1qKGf2s1X674GzCw==", "dev": true, "requires": { "chokidar": "1.7.0", "minimist": "1.2.0", - "reflect-metadata": "0.1.10", - "tsickle": "0.25.5" + "reflect-metadata": "0.1.12", + "tsickle": "0.27.5" } }, "@angular/core": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-5.1.0.tgz", - "integrity": "sha512-duObjve+INoz4wWuqcaJzl1isUyI37RtRblTFXgZBp2n2n0nXJq1CubcfgxQhMMR2d64xWLKg9+d34PvnzaMmg==", + "version": "5.2.10", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-5.2.10.tgz", + "integrity": "sha512-glDuTtHTcAVhfU3NVewxz/W+Iweq5IaeW2tnMa+RKLopYk9fRs8eR5iTixTGvegwKR770vfXg/gR7P6Ii5cYGQ==", "requires": { "tslib": "1.8.0" } }, "@angular/forms": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-5.1.0.tgz", - "integrity": "sha512-2sJqtMht/6vbFg6HwFs0MX4pRhgLt7h2pa6oTH4oBoQ2UF67jCuq4cMljDm9SVxrGw0Q83+/eBk3ER4QnKk48Q==", + "version": "5.2.10", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-5.2.10.tgz", + "integrity": "sha512-XQR4cd1Eey9aDT3CxQ6pbBWSBEg1408ZV/EUblKgMgt4k8PfDiuLSbF+MI/TOYAg3UkcVAxN1no4hWtkou8Rpw==", "requires": { "tslib": "1.8.0" } }, "@angular/http": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@angular/http/-/http-5.1.0.tgz", - "integrity": "sha512-ltSs52OYnWZJEnbxtHoN5LQiH/37F3GxN6iL0TsQdSlw8HzrdcdbmebKlCpfXwhgcgZC48KWbKSaOs5/xVurfQ==", + "version": "5.2.10", + "resolved": "https://registry.npmjs.org/@angular/http/-/http-5.2.10.tgz", + "integrity": "sha512-euEJbxpH+pKBAwGUSo7XvNdods/kY6I4s8OUaJPUMtraQkhE6TJ0OMYvnqmGbdLimsg3ZMxqm54jCOjj9saEOQ==", "requires": { "tslib": "1.8.0" } }, "@angular/material": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@angular/material/-/material-5.0.0.tgz", - "integrity": "sha512-rzF061r4aYgaf2WI12Jk0+Rd4c1VBObdeMDFWRa3XKIcvETtkz+DXFH1n+vIC4YabfPgrdJRPrzdrZ7fKhRz6g==", + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/@angular/material/-/material-5.2.5.tgz", + "integrity": "sha512-IltfBeTJWnmZehOQNQ7KoFs7MGWuZTe0g21hIitGkusVNt1cIoTD24xKH5jwztjH19c04IgiwonpurMKM6pBCQ==", "requires": { "tslib": "1.8.0" } }, "@angular/platform-browser": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-5.1.0.tgz", - "integrity": "sha512-8aeppeASwQv4Fj3B8KBiFHQrKPrwA328AEhlH/HnggCvt0CFffIs2PSqzJBwnOfFWvhFZk020W51B8jrHLQyoQ==", + "version": "5.2.10", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-5.2.10.tgz", + "integrity": "sha512-oF1A0BS1wpTlxfv6YytkFCkztvvtVllnh5IUnoyV+siVT3qogKat9ZmzCmcDJ5SvIDYkY+rXBhumyFzBZ5ufFg==", "requires": { "tslib": "1.8.0" } }, "@angular/platform-browser-dynamic": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-5.1.0.tgz", - "integrity": "sha512-f6Iv4NCYQwBkNeyInZzja8pg0nfUOrxx5H5rEvr0J1bwag2eDofGVPOftha7LDOLVALVOQQiXQBePATMNLB85g==", + "version": "5.2.10", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-5.2.10.tgz", + "integrity": "sha512-TquhIkyR6uXfmzk6RiEl5+8Kk653Wqe4F+pKn5gFi+Z6cDm4nkDlT9kgT3e6c08JHw9fGGAvNmsalq7oS+PnNg==", "requires": { "tslib": "1.8.0" } }, "@angular/router": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-5.1.0.tgz", - "integrity": "sha512-CtOwqeo1IUk4kUs+tUggkYFmuu2fPTZ1G/GP7YK6gd3Jr9OtkMFB7wkmnd5YcaYo3wVeYkJWZdJQAvj6OakMww==", + "version": "5.2.10", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-5.2.10.tgz", + "integrity": "sha512-63op4yExVsm+Ng4dlCeexQdXKYMnzxtmX116V3hY/mHi1MPTR20uPCx55U8xR0kQvxs0ea8tmJxHdMpz76edqA==", "requires": { "tslib": "1.8.0" } @@ -239,18 +347,19 @@ "dev": true }, "@ngtools/webpack": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-1.9.0.tgz", - "integrity": "sha512-+9EFOELj9D7zarsKTiIFSbTL2Pr3jYdRJ/cEuSoTxzZUDq7f3urq9ILbcy3DTaDlZs2CCYKwgz+In8QnDtw4fg==", + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-1.10.2.tgz", + "integrity": "sha512-3u2zg2rarG3qNLSukBClGADWuq/iNn5SQtlSeAbfKzwBeyLGbF0gN1z1tVx1Bcr8YwFzR6NdRePQmJGcoqq1fg==", "dev": true, "requires": { "chalk": "2.2.2", "enhanced-resolve": "3.4.1", "loader-utils": "1.1.0", - "magic-string": "0.22.4", + "magic-string": "0.22.5", "semver": "5.4.1", "source-map": "0.5.7", - "tree-kill": "1.2.0" + "tree-kill": "1.2.0", + "webpack-sources": "1.1.0" } }, "@ngx-translate/core": { @@ -263,25 +372,35 @@ "resolved": "https://registry.npmjs.org/@ngx-translate/http-loader/-/http-loader-2.0.1.tgz", "integrity": "sha1-qmd4jmS/qGUmkad7Ais7QDEgkRM=" }, - "@schematics/angular": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-0.1.10.tgz", - "integrity": "sha512-ykq4FL0WTygkpvIcGDxnxHHT2uvJMWseDeAujmfyZpzdT9X22GOTURNo3LjvOIhhVUpMVZvnAYqjV46KqB702g==", - "dev": true, + "@schematics/package-update": { + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/@schematics/package-update/-/package-update-0.4.9.tgz", + "integrity": "sha512-HHBi94u9vG4IDfOxk6f88re7SBrPd0JUaLVOmDIWXodQvVPo/J+oSGsFwrJirww57fyeeg1J6RvLbbUDeGu1pg==", "requires": { - "@angular-devkit/core": "0.0.22" + "rxjs": "6.0.0-uncanny-rc.7", + "semver": "5.4.1", + "semver-intersect": "1.3.1" + }, + "dependencies": { + "rxjs": { + "version": "6.0.0-uncanny-rc.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.0.0-uncanny-rc.7.tgz", + "integrity": "sha512-mXBJnSpbrotKF83b1sd5uSa7q/J/y99yBArB02l6B1v2QAP18FCn2BwRXfC9O4A+75mfwUAIUWJyLilboF5z2A==", + "requires": { + "tslib": "1.9.0" + } + }, + "tslib": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz", + "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==" + } } }, - "@schematics/schematics": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@schematics/schematics/-/schematics-0.0.10.tgz", - "integrity": "sha512-9vr9W1X6oRp42pbiGRIk3L+T6SoFtHlAGrzbh6rbFQDNXT4UCHarqDigow+DEL6PR2ptXZO9WeLcad4it7zNyA==", - "dev": true - }, "@swimlane/ngx-charts": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@swimlane/ngx-charts/-/ngx-charts-7.0.1.tgz", - "integrity": "sha512-YZNhRpMjhLpbaJK8iwPDj79Czusw12YNGGnrlbn3iwMhH8e3xkZVfzWhRA9RpfbVKo+S7qMhFTSlOhePQ61Zbg==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/@swimlane/ngx-charts/-/ngx-charts-7.3.0.tgz", + "integrity": "sha512-vRepalGJQOiVMBiIhLSuRY0d4nAA6ORSHXGRe8Klqh808NQ9WXR7tvB8zk4MFr496v6iilG8dLIeDwXGY+asOw==", "requires": { "d3-array": "1.2.1", "d3-brush": "1.0.4", @@ -296,10 +415,16 @@ "d3-time-format": "2.1.1" } }, + "@types/file-saver": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@types/file-saver/-/file-saver-1.3.0.tgz", + "integrity": "sha512-fC12hKtEzVkrV/ZRcrmqvpHG/TMYDZtgpAmgMUA4F7KneDaQeFMwmPz8AfygKKJMqsdTi8bL+E+fciaaMLxUhg==", + "dev": true + }, "@types/jasmine": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.8.2.tgz", - "integrity": "sha512-RabEJPjYMpjWqW1qYj4k0rlgP5uzyguoc0yxedJdq7t5h19MYvqhjCR1evM3raZ/peHRxp1Qfl24iawvkibSug==", + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.8.6.tgz", + "integrity": "sha512-clg9raJTY0EOo5pVZKX3ZlMjlYzVU73L71q5OV1jhE2Uezb7oF94jh4CvwrW6wInquQAdhOxJz5VDF2TLUGmmA==", "dev": true }, "@types/jasminewd2": { @@ -308,13 +433,13 @@ "integrity": "sha512-hYDVmQZT5VA2kigd4H4bv7vl/OhlympwREUemqBdOqtrYTo5Ytm12a5W5/nGgGYdanGVxj0x/VhZ7J3hOg/YKg==", "dev": true, "requires": { - "@types/jasmine": "2.8.2" + "@types/jasmine": "2.8.6" } }, "@types/node": { - "version": "8.0.57", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.57.tgz", - "integrity": "sha512-ZxrhcBxlZA7tn0HFf7ebUYfR9aHyBgjyavBLzyrYMYuAMbONBPY4S5O35562iV2FfwnZCjQky3gTDy1B3jSZ2Q==", + "version": "8.10.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.10.tgz", + "integrity": "sha512-p3W/hFzQs76RlYRIZsZc5a9bht6m0TspmWYYbKhRswmLnwj9fsE40EbuGifeu/XWR/c0UJQ1DDbvTxIsm/OOAA==", "dev": true }, "@types/q": { @@ -335,13 +460,30 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "accepts": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", - "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", "dev": true, "requires": { - "mime-types": "2.1.17", + "mime-types": "2.1.18", "negotiator": "0.6.1" + }, + "dependencies": { + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, + "requires": { + "mime-db": "1.33.0" + } + } } }, "ace-builds": { @@ -350,9 +492,9 @@ "integrity": "sha512-Gcz6nv1YOwTrd1cCd5iDHyF15/hsascz25kUdUYC2zvMv1xeTldGrisMeV4+Jq3vv2OGNukzhIu48RB70iY7pA==" }, "acorn": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.2.1.tgz", - "integrity": "sha512-jG0u7c4Ly+3QkkW18V+NRDN+4bWHdln30NL1ZL2AvFZZmQe/BfopYCtghCKKVBUSetZ4QKcyA0pY6/4Gw8Pv8w==", + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz", + "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==", "dev": true }, "acorn-dynamic-import": { @@ -372,6 +514,13 @@ } } }, + "addressparser": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.1.tgz", + "integrity": "sha1-R6++GiqSYhkdtoOOT9HTm0CCF0Y=", + "dev": true, + "optional": true + }, "adm-zip": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.4.tgz", @@ -403,21 +552,20 @@ } }, "ajv": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.1.tgz", - "integrity": "sha1-s4u4h22ehr7plJVqBOch6IskjrI=", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.3.0.tgz", + "integrity": "sha1-FlCkERTvAFdMrBC4Ay2PTBSBLac=", "dev": true, "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.0.0", + "fast-deep-equal": "1.1.0", "fast-json-stable-stringify": "2.0.0", "json-schema-traverse": "0.3.1" } }, "ajv-keywords": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", - "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.1.0.tgz", + "integrity": "sha1-rCsnk5xUPpXSwG5/f1wnvkqlQ74=", "dev": true }, "align-text": { @@ -431,21 +579,58 @@ "repeat-string": "1.6.1" } }, - "alphanum-sort": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", - "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", - "dev": true - }, "amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" }, + "amqplib": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.5.2.tgz", + "integrity": "sha512-l9mCs6LbydtHqRniRwYkKdqxVa6XMz3Vw1fh+2gJaaVgTM6Jk3o8RccAKWKtlhT1US5sWrFh+KKxsVUALURSIA==", + "dev": true, + "optional": true, + "requires": { + "bitsyntax": "0.0.4", + "bluebird": "3.5.1", + "buffer-more-ints": "0.0.2", + "readable-stream": "1.1.14", + "safe-buffer": "5.1.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true, + "optional": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true, + "optional": true + } + } + }, "angular2-lightbox": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/angular2-lightbox/-/angular2-lightbox-1.2.1.tgz", - "integrity": "sha512-nlJrvomrq2UdInJYVHjxmrGHZKGEsnxsEfKb/jHxvDc0fuvAApU1fpyYhOjX/PPz2qOjrM0jvu80u7e4bAhZ/w==" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/angular2-lightbox/-/angular2-lightbox-1.3.0.tgz", + "integrity": "sha512-Bj6Dlt5mNwT/ErIGG+AN0ZnYX/lFITpbxxH+Xq3n8+ctHNMXPZSxnmEloDn2ypCxCIXDwiJBIyyOLBKKBlFBCA==" }, "ansi-html": { "version": "0.0.7", @@ -459,9 +644,9 @@ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "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==", "dev": true, "requires": { "color-convert": "1.9.1" @@ -471,7 +656,6 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", - "dev": true, "requires": { "micromatch": "2.3.11", "normalize-path": "2.1.1" @@ -518,7 +702,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, "requires": { "arr-flatten": "1.1.0" } @@ -526,7 +709,12 @@ "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, "array-find-index": { @@ -547,7 +735,7 @@ "dev": true, "requires": { "define-properties": "1.1.2", - "es-abstract": "1.10.0" + "es-abstract": "1.11.0" } }, "array-slice": { @@ -574,13 +762,12 @@ "array-unique": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" }, "arraybuffer.slice": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz", - "integrity": "sha1-8zshWfBTKj8xB6JywMz70a0peco=", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", "dev": true }, "arrify": { @@ -602,9 +789,9 @@ "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" }, "asn1.js": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.2.tgz", - "integrity": "sha512-b/OsSjvWEo8Pi8H0zsDd2P6Uqo2TK2pH8gNLSJtNLM2Db0v2QaAZ0pBQJXVjAn4gBuugeVDr7s63ZogpUIwWDg==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", "dev": true, "requires": { "bn.js": "4.11.8", @@ -626,6 +813,19 @@ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=" }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "ast-types": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.3.tgz", + "integrity": "sha512-XA5o5dsNw8MhyW0Q7MWXJWc4oOzZKbdsEJq45h7c8q/d9DwWZ5F2ugUc1PuMLPGsUnphCt/cNDHu8JeBbxf1qA==", + "dev": true, + "optional": true + }, "async": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", @@ -638,14 +838,19 @@ "async-each": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", - "dev": true + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=" }, "async-foreach": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=" }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "dev": true + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -656,17 +861,23 @@ "resolved": "https://registry.npmjs.org/atoa/-/atoa-1.0.0.tgz", "integrity": "sha1-DMDpGkgOc4+SPrwQNnZHF3mzSkk=" }, + "atob": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", + "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=", + "dev": true + }, "autoprefixer": { - "version": "6.7.7", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", - "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-7.2.6.tgz", + "integrity": "sha512-Iq8TRIB+/9eQ8rbGhcP7ct5cYb/3qjNYAR2SnzLCEcwF6rvVOax8+9+fccgXk4bEhQGjOZd5TLhsksmAdsbGqQ==", "dev": true, "requires": { - "browserslist": "1.7.7", - "caniuse-db": "1.0.30000780", + "browserslist": "2.11.3", + "caniuse-lite": "1.0.30000819", "normalize-range": "0.1.2", "num2fraction": "1.2.2", - "postcss": "5.2.18", + "postcss": "6.0.21", "postcss-value-parser": "3.3.0" } }, @@ -680,6 +891,16 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" }, + "axios": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.15.3.tgz", + "integrity": "sha1-LJ1jiy4ZGgjqHWzJiOrda6W9wFM=", + "dev": true, + "optional": true, + "requires": { + "follow-redirects": "1.0.0" + } + }, "babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", @@ -719,9 +940,9 @@ } }, "babel-generator": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.0.tgz", - "integrity": "sha1-rBriAHC3n248odMmlhMFN3TyDcU=", + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", "dev": true, "requires": { "babel-messages": "6.23.0", @@ -732,14 +953,6 @@ "lodash": "4.17.4", "source-map": "0.5.7", "trim-right": "1.0.1" - }, - "dependencies": { - "jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", - "dev": true - } } }, "babel-messages": { @@ -757,8 +970,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.2", - "regenerator-runtime": "0.11.0" + "core-js": "2.5.5", + "regenerator-runtime": "0.11.1" } }, "babel-template": { @@ -787,7 +1000,7 @@ "babylon": "6.18.0", "debug": "2.6.9", "globals": "9.18.0", - "invariant": "2.2.2", + "invariant": "2.2.4", "lodash": "4.17.4" } }, @@ -820,6 +1033,38 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, "base64-arraybuffer": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", @@ -827,9 +1072,9 @@ "dev": true }, "base64-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", - "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.3.tgz", + "integrity": "sha512-MsAhsUW1GxCdgYSO6tAfZrNapmUKk7mWx/k5mFY/A1gBtkaCaNapTg+FExCw1r9yeaZhqx/xPg43xgTFH6KL5w==", "dev": true }, "base64id": { @@ -871,8 +1116,51 @@ "binary-extensions": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", - "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", - "dev": true + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=" + }, + "bitsyntax": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.0.4.tgz", + "integrity": "sha1-6xDMb4K4xJDj6FaY8H6D1G4MuoI=", + "dev": true, + "optional": true, + "requires": { + "buffer-more-ints": "0.0.2" + } + }, + "bl": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", + "integrity": "sha1-/cqHGplxOqANGeO7ukHER4emU5g=", + "dev": true, + "optional": true, + "requires": { + "readable-stream": "2.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true, + "optional": true + } + } }, "blob": { "version": "0.0.4", @@ -923,13 +1211,13 @@ "bytes": "3.0.0", "content-type": "1.0.4", "debug": "2.6.9", - "depd": "1.1.1", + "depd": "1.1.2", "http-errors": "1.6.2", "iconv-lite": "0.4.19", "on-finished": "2.3.0", "qs": "6.5.1", "raw-body": "2.3.2", - "type-is": "1.6.15" + "type-is": "1.6.16" }, "dependencies": { "qs": { @@ -950,7 +1238,7 @@ "deep-equal": "1.0.1", "dns-equal": "1.0.0", "dns-txt": "2.0.2", - "multicast-dns": "6.2.1", + "multicast-dns": "6.2.3", "multicast-dns-service-types": "1.1.0" } }, @@ -989,7 +1277,6 @@ "version": "1.8.5", "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, "requires": { "expand-range": "1.8.2", "preserve": "0.2.0", @@ -1045,7 +1332,7 @@ "dev": true, "requires": { "bn.js": "4.11.8", - "randombytes": "2.0.5" + "randombytes": "2.0.6" } }, "browserify-sign": { @@ -1073,13 +1360,13 @@ } }, "browserslist": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", - "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", + "version": "2.11.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", + "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==", "dev": true, "requires": { - "caniuse-db": "1.0.30000780", - "electron-to-chromium": "1.3.28" + "caniuse-lite": "1.0.30000819", + "electron-to-chromium": "1.3.40" } }, "buffer": { @@ -1088,23 +1375,51 @@ "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", "dev": true, "requires": { - "base64-js": "1.2.1", - "ieee754": "1.1.8", + "base64-js": "1.2.3", + "ieee754": "1.1.10", "isarray": "1.0.0" } }, + "buffer-from": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz", + "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==", + "dev": true + }, "buffer-indexof": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", "dev": true }, + "buffer-more-ints": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz", + "integrity": "sha1-JrOIXRD6E9t/wBquOquHAZngEkw=", + "dev": true + }, "buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", "dev": true }, + "buildmail": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/buildmail/-/buildmail-4.0.1.tgz", + "integrity": "sha1-h393OLeHKYccmhBeO4N9K+EaenI=", + "dev": true, + "optional": true, + "requires": { + "addressparser": "1.0.1", + "libbase64": "0.1.0", + "libmime": "3.0.0", + "libqp": "1.1.0", + "nodemailer-fetch": "1.6.0", + "nodemailer-shared": "1.1.0", + "punycode": "1.4.1" + } + }, "builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", @@ -1123,9 +1438,9 @@ "dev": true }, "cacache": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.1.tgz", - "integrity": "sha512-dRHYcs9LvG9cHgdPzjiI+/eS7e1xRhULrcyOx04RZQsszNJXU2SL9CyG60yLnge282Qq5nwTv+ieK2fH+WPZmA==", + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", + "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", "dev": true, "requires": { "bluebird": "3.5.1", @@ -1133,17 +1448,62 @@ "glob": "7.1.2", "graceful-fs": "4.1.11", "lru-cache": "4.1.1", - "mississippi": "1.3.0", + "mississippi": "2.0.0", "mkdirp": "0.5.1", "move-concurrently": "1.0.1", "promise-inflight": "1.0.1", "rimraf": "2.6.2", - "ssri": "5.0.0", + "ssri": "5.3.0", "unique-filename": "1.1.0", - "y18n": "3.2.1" + "y18n": "4.0.0" + }, + "dependencies": { + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + } } }, - "callsite": { + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "cache-loader": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cache-loader/-/cache-loader-1.2.2.tgz", + "integrity": "sha512-rsGh4SIYyB9glU+d0OcHwiXHXBoUgDhHZaQ1KAbiXqfz1CDPxtTboh1gPbJ0q2qdO8a9lfcjgC5CJ2Ms32y5bw==", + "dev": true, + "requires": { + "loader-utils": "1.1.0", + "mkdirp": "0.5.1", + "neo-async": "2.5.0", + "schema-utils": "0.4.5" + } + }, + "callsite": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", @@ -1173,22 +1533,10 @@ "map-obj": "1.0.1" } }, - "caniuse-api": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.6.1.tgz", - "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=", - "dev": true, - "requires": { - "browserslist": "1.7.7", - "caniuse-db": "1.0.30000780", - "lodash.memoize": "4.1.2", - "lodash.uniq": "4.5.0" - } - }, - "caniuse-db": { - "version": "1.0.30000780", - "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000780.tgz", - "integrity": "sha1-jRl3Vh0A/w8O0ra2YUAyirRQTAo=", + "caniuse-lite": { + "version": "1.0.30000819", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000819.tgz", + "integrity": "sha512-9i1d8eiKA6dLvsMrVrXOTP9/1sd9iIv4iC/UbPbIa9iQd9Gcnozi2sQ0d69TiQY9l7Alt7YIWISOBwyGSM6H0Q==", "dev": true }, "caseless": { @@ -1204,14 +1552,6 @@ "requires": { "align-text": "0.1.4", "lazy-cache": "1.0.4" - }, - "dependencies": { - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true - } } }, "chalk": { @@ -1220,22 +1560,15 @@ "integrity": "sha512-LvixLAQ4MYhbf7hgL4o5PeK32gJKvVzDRiSNIApDofQvyhl8adgG2lJVXn4+ekQoK7HL9RF8lqxwerpe0x2pCw==", "dev": true, "requires": { - "ansi-styles": "3.2.0", + "ansi-styles": "3.2.1", "escape-string-regexp": "1.0.5", "supports-color": "4.5.0" } }, - "charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", - "dev": true - }, "chokidar": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", - "dev": true, "requires": { "anymatch": "1.3.2", "async-each": "1.0.1", @@ -1245,23 +1578,6 @@ "is-glob": "2.0.1", "path-is-absolute": "1.0.1", "readdirp": "2.1.0" - }, - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - } } }, "chownr": { @@ -1281,51 +1597,107 @@ } }, "circular-dependency-plugin": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-4.3.0.tgz", - "integrity": "sha512-L3W9L1S0wC64rq+QSaZzmWnJW7cVBgimxI2lNEFEX5biwlRG8EHRM68JFi+CX5ZkCGUWJHIpnhdVs181Zlq3wA==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-4.4.0.tgz", + "integrity": "sha512-yEFtUNUYT4jBykEX5ZOHw+5goA3glGZr9wAXIQqoyakjz5H5TeUmScnWRc52douAhb9eYzK3s7V6bXfNnjFdzg==", "dev": true }, - "clap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", - "integrity": "sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA==", + "circular-json": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.3.tgz", + "integrity": "sha512-YlxLOimeIoQGHnMe3kbf8qIV2Bj7uXLbljMPRguNT49GmSAzooNfS9EJ91rSJKbLBOOzM5agvtx0WyechZN/Hw==", + "dev": true + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, "requires": { - "chalk": "1.1.3" + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" }, "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } } }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", "dev": true } } }, "clean-css": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.9.tgz", - "integrity": "sha1-Nc7ornaHpJuYA09w3gDE7dOCYwE=", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.11.tgz", + "integrity": "sha1-Ls3xRaujj1R0DybO/Q/z4D4SXWo=", "dev": true, "requires": { "source-map": "0.5.7" @@ -1342,21 +1714,38 @@ } }, "clone": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", "dev": true }, "clone-deep": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.3.0.tgz", - "integrity": "sha1-NIxhrpzb4O3+BT2R/0zFIdeQ7eg=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-2.0.2.tgz", + "integrity": "sha512-SZegPTKjCgpQH63E+eN6mVEEPdQBOUzjyJm5Pora4lrwWRFS8I0QAxV/KD6vV/i0WuijHZWQC1fMsPEdxfdVCQ==", "dev": true, "requires": { "for-own": "1.0.0", "is-plain-object": "2.0.4", - "kind-of": "3.2.2", - "shallow-clone": "0.1.2" + "kind-of": "6.0.2", + "shallow-clone": "1.0.0" + }, + "dependencies": { + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } } }, "co": { @@ -1364,24 +1753,15 @@ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" }, - "coa": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz", - "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=", - "dev": true, - "requires": { - "q": "1.5.1" - } - }, "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=" }, "codelyzer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-4.0.1.tgz", - "integrity": "sha512-MsOcaiLqcBK7hjHbfp9HZrflqWg5tD9A5qVSXkW208OJ8pkf63id8IiOjEiK/XU3o70W8tWbFKi1tAOwiJDMrQ==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-4.2.1.tgz", + "integrity": "sha512-CKwfgpfkqi9dyzy4s6ELaxJ54QgJ6A8iTSsM4bzHbLuTpbKncvNc3DUlCvpnkHBhK47gEf4qFsWoYqLrJPhy6g==", "dev": true, "requires": { "app-root-path": "2.0.1", @@ -1392,15 +1772,14 @@ "sprintf-js": "1.0.3" } }, - "color": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", - "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", "dev": true, "requires": { - "clone": "1.0.3", - "color-convert": "1.9.1", - "color-string": "0.3.0" + "map-visit": "1.0.0", + "object-visit": "1.0.1" } }, "color-convert": { @@ -1418,26 +1797,6 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "color-string": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", - "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "colormin": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz", - "integrity": "sha1-6i90IKcrlogaOKrlnsEkpvcpgTM=", - "dev": true, - "requires": { - "color": "0.11.4", - "css-color-names": "0.0.4", - "has": "1.0.1" - } - }, "colors": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", @@ -1467,9 +1826,9 @@ "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" }, "common-tags": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.5.1.tgz", - "integrity": "sha512-NrUYGY5TApAk9KB+IZXkR3GR4tA3g26HDsoiGt4kCMHZ727gOGkC+UNfq0Z22jE15bLkc/6RV5Jw1RBW6Usg6A==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.7.2.tgz", + "integrity": "sha512-joj9ZlUOjCrwdbmiLqafeUSgkUM74NqhLsZtSqDmhKudaIY197zTrb8JMl31fMnCUuxwFT23eC/oWvrZzDLRJQ==", "dev": true, "requires": { "babel-runtime": "6.26.0" @@ -1481,6 +1840,12 @@ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, + "compare-versions": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.1.0.tgz", + "integrity": "sha512-4hAxDSBypT/yp2ySFD346So6Ragw5xmBn/e/agIGl3bZr6DLUqnoRZPusxKrXdYRZpgexO9daejmIenlq/wrIQ==", + "dev": true + }, "component-bind": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", @@ -1488,9 +1853,9 @@ "dev": true }, "component-emitter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz", - "integrity": "sha1-KWWU8nU9qmOZbSrwjRWpURbJrsM=", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", "dev": true }, "component-inherit": { @@ -1500,23 +1865,31 @@ "dev": true }, "compressible": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.12.tgz", - "integrity": "sha1-xZpcmdt2dn6YdlAOJx72OzSTvWY=", + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.13.tgz", + "integrity": "sha1-DRAgq5JLL9tNYnmHXH1tq6a6p6k=", "dev": true, "requires": { - "mime-db": "1.30.0" + "mime-db": "1.33.0" + }, + "dependencies": { + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true + } } }, "compression": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.1.tgz", - "integrity": "sha1-7/JgPvwuIs+G810uuTWJ+YdTc9s=", + "version": "1.7.2", + "resolved": "http://registry.npmjs.org/compression/-/compression-1.7.2.tgz", + "integrity": "sha1-qv+81qr4VLROuygDU9WtFlH1mmk=", "dev": true, "requires": { - "accepts": "1.3.4", + "accepts": "1.3.5", "bytes": "3.0.0", - "compressible": "2.0.12", + "compressible": "2.0.13", "debug": "2.6.9", "on-headers": "1.0.1", "safe-buffer": "5.1.1", @@ -1529,42 +1902,49 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "concat-stream": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", - "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, "requires": { + "buffer-from": "1.0.0", "inherits": "2.0.3", "readable-stream": "2.3.3", "typedarray": "0.0.6" } }, "connect": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.5.tgz", - "integrity": "sha1-+43ee6B2OHfQ7J352sC0tA5yx9o=", + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", + "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", "dev": true, "requires": { "debug": "2.6.9", - "finalhandler": "1.0.6", + "finalhandler": "1.1.0", "parseurl": "1.3.2", "utils-merge": "1.0.1" }, "dependencies": { "finalhandler": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.6.tgz", - "integrity": "sha1-AHrqM9Gk0+QgF/YkhIrVjSEvgU8=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", + "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", "dev": true, "requires": { "debug": "2.6.9", - "encodeurl": "1.0.1", + "encodeurl": "1.0.2", "escape-html": "1.0.3", "on-finished": "2.3.0", "parseurl": "1.3.2", "statuses": "1.3.1", "unpipe": "1.0.0" } + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "dev": true } } }, @@ -1647,38 +2027,49 @@ "run-queue": "1.0.3" } }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, "copy-webpack-plugin": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.2.3.tgz", - "integrity": "sha512-cL/Wl3Y1QmmKThl/mWeGB+HH3YH+25tn8nhqEGsZda4Yn7GqGnDZ+TbeKJ7A6zvrxyNhhuviYAxn/tCyyAqh8Q==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.4.3.tgz", + "integrity": "sha512-v4THQ24Tks2NkyOvZuFDgZVfDD9YaA9rwYLZTrWg2GHIA8lrH5DboEyeoorh5Skki+PUbgSmnsCwhMWqYrQZrA==", "dev": true, "requires": { - "bluebird": "3.5.1", - "glob": "7.1.2", + "cacache": "10.0.4", + "find-cache-dir": "1.0.0", + "globby": "7.1.1", "is-glob": "4.0.0", - "loader-utils": "0.2.17", - "lodash": "4.17.4", - "minimatch": "3.0.4" + "loader-utils": "1.1.0", + "minimatch": "3.0.4", + "p-limit": "1.2.0", + "serialize-javascript": "1.4.0" }, "dependencies": { - "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "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-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", "dev": true, "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1", - "object-assign": "4.1.1" + "is-extglob": "2.1.1" } } } }, "core-js": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.2.tgz", - "integrity": "sha1-vEZIZW59ydyA19PHu8Fy2W50TmM=" + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.5.tgz", + "integrity": "sha1-sU3ek2xkDAV5prUMq8wTLdYSfjs=" }, "core-object": { "version": "3.1.5", @@ -1701,7 +2092,7 @@ "dev": true, "requires": { "is-directory": "0.3.1", - "js-yaml": "3.7.0", + "js-yaml": "3.11.0", "minimist": "1.2.0", "object-assign": "4.1.1", "os-homedir": "1.0.2", @@ -1728,7 +2119,7 @@ "cipher-base": "1.0.4", "inherits": "2.0.3", "ripemd160": "2.0.1", - "sha.js": "2.4.9" + "sha.js": "2.4.11" } }, "create-hmac": { @@ -1742,7 +2133,7 @@ "inherits": "2.0.3", "ripemd160": "2.0.1", "safe-buffer": "5.1.1", - "sha.js": "2.4.9" + "sha.js": "2.4.11" } }, "cross-spawn": { @@ -1762,12 +2153,6 @@ "custom-event": "1.0.0" } }, - "crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", - "dev": true - }, "cryptiles": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", @@ -1791,36 +2176,8 @@ "inherits": "2.0.3", "pbkdf2": "3.0.14", "public-encrypt": "4.0.0", - "randombytes": "2.0.5", - "randomfill": "1.0.3" - } - }, - "css-color-names": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", - "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", - "dev": true - }, - "css-loader": { - "version": "0.28.7", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.28.7.tgz", - "integrity": "sha512-GxMpax8a/VgcfRrVy0gXD6yLd5ePYbXX/5zGgTVYp4wXtJklS8Z2VaUArJgc//f6/Dzil7BaJObdSv8eKKCPgg==", - "dev": true, - "requires": { - "babel-code-frame": "6.26.0", - "css-selector-tokenizer": "0.7.0", - "cssnano": "3.10.0", - "icss-utils": "2.1.0", - "loader-utils": "1.1.0", - "lodash.camelcase": "4.3.0", - "object-assign": "4.1.1", - "postcss": "5.2.18", - "postcss-modules-extract-imports": "1.1.0", - "postcss-modules-local-by-default": "1.2.0", - "postcss-modules-scope": "1.1.0", - "postcss-modules-values": "1.3.0", - "postcss-value-parser": "3.3.0", - "source-list-map": "2.0.0" + "randombytes": "2.0.6", + "randomfill": "1.0.4" } }, "css-parse": { @@ -1873,56 +2230,6 @@ "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=", "dev": true }, - "cssnano": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz", - "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=", - "dev": true, - "requires": { - "autoprefixer": "6.7.7", - "decamelize": "1.2.0", - "defined": "1.0.0", - "has": "1.0.1", - "object-assign": "4.1.1", - "postcss": "5.2.18", - "postcss-calc": "5.3.1", - "postcss-colormin": "2.2.2", - "postcss-convert-values": "2.6.1", - "postcss-discard-comments": "2.0.4", - "postcss-discard-duplicates": "2.1.0", - "postcss-discard-empty": "2.1.0", - "postcss-discard-overridden": "0.1.1", - "postcss-discard-unused": "2.2.3", - "postcss-filter-plugins": "2.0.2", - "postcss-merge-idents": "2.1.7", - "postcss-merge-longhand": "2.0.2", - "postcss-merge-rules": "2.1.2", - "postcss-minify-font-values": "1.0.5", - "postcss-minify-gradients": "1.0.5", - "postcss-minify-params": "1.2.2", - "postcss-minify-selectors": "2.1.1", - "postcss-normalize-charset": "1.1.1", - "postcss-normalize-url": "3.0.8", - "postcss-ordered-values": "2.2.3", - "postcss-reduce-idents": "2.4.0", - "postcss-reduce-initial": "1.0.1", - "postcss-reduce-transforms": "1.0.4", - "postcss-svgo": "2.1.6", - "postcss-unique-selectors": "2.0.2", - "postcss-value-parser": "3.3.0", - "postcss-zindex": "2.2.0" - } - }, - "csso": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/csso/-/csso-2.3.2.tgz", - "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=", - "dev": true, - "requires": { - "clap": "1.2.3", - "source-map": "0.5.7" - } - }, "cuint": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", @@ -1954,13 +2261,13 @@ "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "dev": true, "requires": { - "es5-ext": "0.10.37" + "es5-ext": "0.10.41" } }, "d3": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/d3/-/d3-4.12.0.tgz", - "integrity": "sha512-ibAzFJrj1uuX+wIy29baTx9JebA5i670UKlp+H3c9pg0w8PKl8jpj4zf64MmLPVBXm2vA1i29obnWuM/rmyfWA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-5.1.0.tgz", + "integrity": "sha512-2ltUUsAuolg5+AfgRBkZBFOUcR+UsWc2vAixBSiw6cFqdSCEufPavYI6lPdL68dgNOaMp4sggwJ3BnJElm7tyQ==", "requires": { "d3-array": "1.2.1", "d3-axis": "1.0.8", @@ -1968,10 +2275,12 @@ "d3-chord": "1.0.4", "d3-collection": "1.0.4", "d3-color": "1.0.3", + "d3-contour": "1.2.0", "d3-dispatch": "1.0.3", "d3-drag": "1.2.1", "d3-dsv": "1.0.8", "d3-ease": "1.0.3", + "d3-fetch": "1.1.0", "d3-force": "1.1.0", "d3-format": "1.2.1", "d3-geo": "1.9.0", @@ -1980,10 +2289,9 @@ "d3-path": "1.0.5", "d3-polygon": "1.0.3", "d3-quadtree": "1.0.3", - "d3-queue": "3.0.7", "d3-random": "1.1.0", - "d3-request": "1.0.6", - "d3-scale": "1.0.7", + "d3-scale": "2.0.0", + "d3-scale-chromatic": "1.2.0", "d3-selection": "1.2.0", "d3-shape": "1.2.0", "d3-time": "1.0.8", @@ -1992,6 +2300,21 @@ "d3-transition": "1.1.1", "d3-voronoi": "1.1.2", "d3-zoom": "1.7.1" + }, + "dependencies": { + "d3-scale": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-2.0.0.tgz", + "integrity": "sha512-Sa2Ny6CoJT7x6dozxPnvUQT61epGWsgppFvnNl8eJEzfJBG0iDBBTJAtz2JKem7Mb+NevnaZiDiIDHsuWkv6vg==", + "requires": { + "d3-array": "1.2.1", + "d3-collection": "1.0.4", + "d3-format": "1.2.1", + "d3-interpolate": "1.1.6", + "d3-time": "1.0.8", + "d3-time-format": "2.1.1" + } + } } }, "d3-array": { @@ -2035,6 +2358,14 @@ "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.0.3.tgz", "integrity": "sha1-vHZD/KjlOoNH4vva/6I2eWtYUJs=" }, + "d3-contour": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-1.2.0.tgz", + "integrity": "sha512-nDzZ2KDnrgTrhMjV8TH0RNrljk6uPNAGkG/v/1SKNVvJa2JU8szjh7o2ZYTX8yufA2oCI5HyeMqbzwiB+oDoIA==", + "requires": { + "d3-array": "1.2.1" + } + }, "d3-dispatch": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.3.tgz", @@ -2064,6 +2395,14 @@ "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.3.tgz", "integrity": "sha1-aL+8NJM4o4DETYrMT7wzBKotjA4=" }, + "d3-fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.1.0.tgz", + "integrity": "sha512-j+V4vtT6dceQbcKYLtpTueB8Zvc+wb9I93WaFtEQIYNADXl0c1ZJMN3qQo0CssiTsAqK8pePwc7f4qiW+b0WOg==", + "requires": { + "d3-dsv": "1.0.8" + } + }, "d3-force": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.1.0.tgz", @@ -2116,27 +2455,11 @@ "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.3.tgz", "integrity": "sha1-rHmH4+I/6AWpkPKOG1DTj8uCJDg=" }, - "d3-queue": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/d3-queue/-/d3-queue-3.0.7.tgz", - "integrity": "sha1-yTouVLQXwJWRKdfXP2z31Ckudhg=" - }, "d3-random": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.0.tgz", "integrity": "sha1-ZkLlBsb6OmSFldKyRpeIqNElKdM=" }, - "d3-request": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-request/-/d3-request-1.0.6.tgz", - "integrity": "sha512-FJj8ySY6GYuAJHZMaCQ83xEYE4KbkPkmxZ3Hu6zA1xxG2GD+z6P+Lyp+zjdsHf0xEbp2xcluDI50rCS855EQ6w==", - "requires": { - "d3-collection": "1.0.4", - "d3-dispatch": "1.0.3", - "d3-dsv": "1.0.8", - "xmlhttprequest": "1.8.0" - } - }, "d3-scale": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-1.0.7.tgz", @@ -2151,6 +2474,15 @@ "d3-time-format": "2.1.1" } }, + "d3-scale-chromatic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-1.2.0.tgz", + "integrity": "sha512-qQUhLi8fPe/F0b0M46C6eFUbms5IIMHuhJ5DKjjzBUvm1b6aPtygJzGbrMdMUD/ckLBq+NdWwHeN2cpMDp4Q5Q==", + "requires": { + "d3-color": "1.0.3", + "d3-interpolate": "1.1.6" + } + }, "d3-selection": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.2.0.tgz", @@ -2227,6 +2559,19 @@ } } }, + "data-uri-to-buffer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", + "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==", + "dev": true, + "optional": true + }, + "date-format": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", + "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", + "dev": true + }, "date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", @@ -2247,12 +2592,25 @@ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, - "deep-equal": { - "version": "1.0.1", + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "deep-equal": { + "version": "1.0.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", "dev": true }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true, + "optional": true + }, "default-require-extensions": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", @@ -2272,11 +2630,44 @@ "object-keys": "1.0.11" } }, - "defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "degenerator": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", + "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", + "dev": true, + "optional": true, + "requires": { + "ast-types": "0.11.3", + "escodegen": "1.9.1", + "esprima": "3.1.3" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true, + "optional": true + } + } }, "del": { "version": "3.0.0", @@ -2286,12 +2677,33 @@ "requires": { "globby": "6.1.0", "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.0", + "is-path-in-cwd": "1.0.1", "p-map": "1.2.0", "pify": "3.0.0", "rimraf": "2.6.2" }, "dependencies": { + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", @@ -2317,9 +2729,9 @@ "dev": true }, "depd": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", "dev": true }, "des.js": { @@ -2360,9 +2772,9 @@ "dev": true }, "diff": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz", - "integrity": "sha512-QpVuMTEoJMF7cKzi6bvWhRulU1fZqZnvyVQgNhPaxxuTYwyjn/j1v9falseQ/uXWwPnO56RBfwtg4h/EQXmucA==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, "diffie-hellman": { @@ -2373,7 +2785,34 @@ "requires": { "bn.js": "4.11.8", "miller-rabin": "4.0.1", - "randombytes": "2.0.5" + "randombytes": "2.0.6" + } + }, + "dir-glob": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", + "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", + "dev": true, + "requires": { + "arrify": "1.0.1", + "path-type": "3.0.0" + }, + "dependencies": { + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } } }, "dns-equal": { @@ -2383,9 +2822,9 @@ "dev": true }, "dns-packet": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.2.2.tgz", - "integrity": "sha512-kN+DjfGF7dJGUL7nWRktL9Z18t1rWP3aQlyZdY8XlpvU3Nc6GeFTQApftcjtWKxAZfiggZSGrCEoszNgvnpwDg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", + "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", "dev": true, "requires": { "ip": "1.1.5", @@ -2449,9 +2888,9 @@ } }, "domain-browser": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", - "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", "dev": true }, "domelementtype": { @@ -2479,6 +2918,13 @@ "domelementtype": "1.3.0" } }, + "double-ended-queue": { + "version": "2.1.0-0", + "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", + "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=", + "dev": true, + "optional": true + }, "dragula": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/dragula/-/dragula-3.7.2.tgz", @@ -2489,12 +2935,12 @@ } }, "duplexify": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", - "integrity": "sha512-j5goxHTwVED1Fpe5hh3q9R93Kip0Bg2KVAt4f8CEYM3UEwYcPSvWbXaUQOzdX/HtiNomipv+gU7ASQPDbV7pGQ==", + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.4.tgz", + "integrity": "sha512-JzYSLYMhoVVBe8+mbHQ4KgpvHpm0DZpJuL8PY93Vyv1fW7jYJ90LoXa1di/CVbJM+TgMs91rbDapE/RNIfnJsA==", "dev": true, "requires": { - "end-of-stream": "1.4.0", + "end-of-stream": "1.4.1", "inherits": "2.0.3", "readable-stream": "2.3.3", "stream-shift": "1.0.0" @@ -2522,9 +2968,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.28", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.28.tgz", - "integrity": "sha1-jdTmRYCGZE6fnwoc8y4qH53/2e4=", + "version": "1.3.40", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.40.tgz", + "integrity": "sha1-H71tl779crim+SHcONIkE9L2/d8=", "dev": true }, "elliptic": { @@ -2555,116 +3001,87 @@ "dev": true }, "encodeurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", - "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", "dev": true }, "end-of-stream": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", - "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", "dev": true, "requires": { "once": "1.4.0" } }, "engine.io": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-1.8.3.tgz", - "integrity": "sha1-jef5eJXSDTm4X4ju7nd7K9QrE9Q=", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.1.5.tgz", + "integrity": "sha512-D06ivJkYxyRrcEe0bTpNnBQNgP9d3xog+qZlLbui8EsMr/DouQpf5o9FzJnWYHEYE0YsFHllUv2R1dkgYZXHcA==", "dev": true, "requires": { - "accepts": "1.3.3", + "accepts": "1.3.5", "base64id": "1.0.0", "cookie": "0.3.1", - "debug": "2.3.3", - "engine.io-parser": "1.3.2", - "ws": "1.1.2" + "debug": "3.1.0", + "engine.io-parser": "2.1.2", + "uws": "9.14.0", + "ws": "3.3.3" }, "dependencies": { - "accepts": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz", - "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=", - "dev": true, - "requires": { - "mime-types": "2.1.17", - "negotiator": "0.6.1" - } - }, "debug": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz", - "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { - "ms": "0.7.2" + "ms": "2.0.0" } - }, - "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", - "dev": true } } }, "engine.io-client": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-1.8.3.tgz", - "integrity": "sha1-F5jtk0USRkU9TG9jXXogH+lA1as=", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.1.6.tgz", + "integrity": "sha512-hnuHsFluXnsKOndS4Hv6SvUrgdYx1pk2NqfaDMW+GWdgfU3+/V25Cj7I8a0x92idSpa5PIhJRKxPvp9mnoLsfg==", "dev": true, "requires": { "component-emitter": "1.2.1", "component-inherit": "0.0.3", - "debug": "2.3.3", - "engine.io-parser": "1.3.2", + "debug": "3.1.0", + "engine.io-parser": "2.1.2", "has-cors": "1.1.0", "indexof": "0.0.1", - "parsejson": "0.0.3", "parseqs": "0.0.5", "parseuri": "0.0.5", - "ws": "1.1.2", - "xmlhttprequest-ssl": "1.5.3", + "ws": "3.3.3", + "xmlhttprequest-ssl": "1.5.5", "yeast": "0.1.2" }, "dependencies": { - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true - }, "debug": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz", - "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { - "ms": "0.7.2" + "ms": "2.0.0" } - }, - "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", - "dev": true } } }, "engine.io-parser": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.3.2.tgz", - "integrity": "sha1-k3sHnwAH0Ik+xW1GyyILjLQ1Igo=", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", + "integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==", "dev": true, "requires": { "after": "0.8.2", - "arraybuffer.slice": "0.0.6", + "arraybuffer.slice": "0.0.7", "base64-arraybuffer": "0.1.5", "blob": "0.0.4", - "has-binary": "0.1.7", - "wtf-8": "1.0.0" + "has-binary2": "1.0.2" } }, "enhanced-resolve": { @@ -2691,12 +3108,12 @@ "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=" }, "errno": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz", - "integrity": "sha1-uJbiOp5ei6M4cfyZar02NfyaHH0=", + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", "dev": true, "requires": { - "prr": "0.0.0" + "prr": "1.0.1" } }, "error-ex": { @@ -2708,9 +3125,9 @@ } }, "es-abstract": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.10.0.tgz", - "integrity": "sha512-/uh/DhdqIOSkAWifU+8nG78vlQxdLckUdI/sPgy0VhuXi2qJ7T8czBmqIYtLQVpCIFYafChnsRsB5pyb1JdmCQ==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.11.0.tgz", + "integrity": "sha512-ZnQrE/lXTTQ39ulXZ+J1DTFazV9qBy61x2bY071B+qGco8Z8q1QddsLdt/EF8Ai9hcWH72dWS0kFqXLxOxqslA==", "dev": true, "requires": { "es-to-primitive": "1.1.1", @@ -2732,13 +3149,14 @@ } }, "es5-ext": { - "version": "0.10.37", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz", - "integrity": "sha1-DudB0Ui4AGm6J9AgOTdWryV978M=", + "version": "0.10.41", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.41.tgz", + "integrity": "sha512-MYK02wXfwTMie5TEJWPolgOsXEmz7wKCQaGzgmRjZOoV6VLG8I5dSv2bn6AOClXhK64gnSQTQ9W9MKvx87J4gw==", "dev": true, "requires": { "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" + "es6-symbol": "3.1.1", + "next-tick": "1.0.0" } }, "es6-iterator": { @@ -2748,7 +3166,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.37", + "es5-ext": "0.10.41", "es6-symbol": "3.1.1" } }, @@ -2759,7 +3177,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.37", + "es5-ext": "0.10.41", "es6-iterator": "2.0.3", "es6-set": "0.1.5", "es6-symbol": "3.1.1", @@ -2779,7 +3197,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.37", + "es5-ext": "0.10.41", "es6-iterator": "2.0.3", "es6-symbol": "3.1.1", "event-emitter": "0.3.5" @@ -2792,7 +3210,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.37" + "es5-ext": "0.10.41" } }, "es6-weak-map": { @@ -2802,7 +3220,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.37", + "es5-ext": "0.10.41", "es6-iterator": "2.0.3", "es6-symbol": "3.1.1" } @@ -2818,6 +3236,36 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, + "escodegen": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.1.tgz", + "integrity": "sha512-6hTjO1NAWkHnDk3OqQ4YrCuwwmGHL9S3nPlzBOUG/R44rda3wLNrfvQ5fkSGjyhHFKM7ALPKcKGrwvCLe0lC7Q==", + "dev": true, + "optional": true, + "requires": { + "esprima": "3.1.3", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.6.1" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true, + "optional": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } + }, "escope": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", @@ -2826,24 +3274,23 @@ "requires": { "es6-map": "0.1.5", "es6-weak-map": "2.0.2", - "esrecurse": "4.2.0", + "esrecurse": "4.2.1", "estraverse": "4.2.0" } }, "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", "dev": true }, "esrecurse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", - "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", "dev": true, "requires": { - "estraverse": "4.2.0", - "object-assign": "4.1.1" + "estraverse": "4.2.0" } }, "estraverse": { @@ -2871,7 +3318,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.37" + "es5-ext": "0.10.41" } }, "eventemitter3": { @@ -2987,7 +3434,6 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, "requires": { "is-posix-bracket": "0.1.1" } @@ -2996,28 +3442,17 @@ "version": "1.8.2", "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true, "requires": { "fill-range": "2.2.3" } }, - "exports-loader": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/exports-loader/-/exports-loader-0.6.4.tgz", - "integrity": "sha1-1w/GEhl1s1/BKDDPUnVL4nQPyIY=", - "dev": true, - "requires": { - "loader-utils": "1.1.0", - "source-map": "0.5.7" - } - }, "express": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.16.2.tgz", - "integrity": "sha1-41xt/i1kt9ygpc1PIXgb4ymeB2w=", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", + "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", "dev": true, "requires": { - "accepts": "1.3.4", + "accepts": "1.3.5", "array-flatten": "1.1.1", "body-parser": "1.18.2", "content-disposition": "0.5.2", @@ -3025,26 +3460,26 @@ "cookie": "0.3.1", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "1.1.1", - "encodeurl": "1.0.1", + "depd": "1.1.2", + "encodeurl": "1.0.2", "escape-html": "1.0.3", "etag": "1.8.1", - "finalhandler": "1.1.0", + "finalhandler": "1.1.1", "fresh": "0.5.2", "merge-descriptors": "1.0.1", "methods": "1.1.2", "on-finished": "2.3.0", "parseurl": "1.3.2", "path-to-regexp": "0.1.7", - "proxy-addr": "2.0.2", + "proxy-addr": "2.0.3", "qs": "6.5.1", "range-parser": "1.2.0", "safe-buffer": "5.1.1", - "send": "0.16.1", - "serve-static": "1.13.1", + "send": "0.16.2", + "serve-static": "1.13.2", "setprototypeof": "1.1.0", - "statuses": "1.3.1", - "type-is": "1.6.15", + "statuses": "1.4.0", + "type-is": "1.6.16", "utils-merge": "1.0.1", "vary": "1.1.2" }, @@ -3068,21 +3503,33 @@ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, "extglob": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, "requires": { "is-extglob": "1.0.0" - }, - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - } } }, "extract-text-webpack-plugin": { @@ -3095,6 +3542,29 @@ "loader-utils": "1.1.0", "schema-utils": "0.3.0", "webpack-sources": "1.1.0" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "schema-utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", + "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", + "dev": true, + "requires": { + "ajv": "5.5.2" + } + } } }, "extsprintf": { @@ -3103,16 +3573,21 @@ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "fast-deep-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", - "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", - "dev": true + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" }, "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true, + "optional": true }, "fastparse": { "version": "1.1.1", @@ -3130,13 +3605,13 @@ } }, "file-loader": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.5.tgz", - "integrity": "sha512-RzGHDatcVNpGISTvCpfUfOGpYuSR7HSsSg87ki+wF6rw1Hm0RALPTiAdsxAq1UwLf0RRhbe22/eHK6nhXspiOQ==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", + "integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==", "dev": true, "requires": { "loader-utils": "1.1.0", - "schema-utils": "0.3.0" + "schema-utils": "0.4.5" } }, "file-saver": { @@ -3144,11 +3619,17 @@ "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-1.3.3.tgz", "integrity": "sha1-zdTETTqiZOrC9o7BZbx5HDSvEjI=" }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, "filename-regex": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" }, "fileset": { "version": "2.0.3", @@ -3164,38 +3645,26 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", - "dev": true, "requires": { "is-number": "2.1.0", "isobject": "2.1.0", "randomatic": "1.1.7", "repeat-element": "1.1.2", "repeat-string": "1.6.1" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } } }, "finalhandler": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", - "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", "dev": true, "requires": { "debug": "2.6.9", - "encodeurl": "1.0.1", + "encodeurl": "1.0.2", "escape-html": "1.0.3", "on-finished": "2.3.0", "parseurl": "1.3.2", - "statuses": "1.3.1", + "statuses": "1.4.0", "unpipe": "1.0.0" } }, @@ -3206,7 +3675,7 @@ "dev": true, "requires": { "commondir": "1.0.1", - "make-dir": "1.1.0", + "make-dir": "1.2.0", "pkg-dir": "2.0.0" } }, @@ -3219,33 +3688,35 @@ "pinkie-promise": "2.0.1" } }, - "flatten": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", - "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=", - "dev": true - }, "flush-write-stream": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.2.tgz", - "integrity": "sha1-yBuQ2HRnZvGmCaRoCZRsRd2K5Bc=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", + "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", "dev": true, "requires": { "inherits": "2.0.3", "readable-stream": "2.3.3" } }, + "follow-redirects": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.0.0.tgz", + "integrity": "sha1-jjQpjL0uF28lTv/sdaHHjMhJ/Tc=", + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.9" + } + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" }, "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", "requires": { "for-in": "1.0.2" } @@ -3277,6 +3748,15 @@ "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", "dev": true }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "0.2.2" + } + }, "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -3341,31 +3821,71 @@ "rimraf": "2.6.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 - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "requires": { - "aproba": "1.2.0", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" - } - }, - "gaze": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.2.tgz", - "integrity": "sha1-hHIkZ3rbiHDWeSV+0ziP22HkAQU=", + "ftp": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", + "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", + "dev": true, + "optional": true, + "requires": { + "readable-stream": "1.1.14", + "xregexp": "2.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true, + "optional": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true, + "optional": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "gaze": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.2.tgz", + "integrity": "sha1-hHIkZ3rbiHDWeSV+0ziP22HkAQU=", "requires": { "globule": "1.2.0" } @@ -3399,6 +3919,27 @@ "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true }, + "get-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.1.tgz", + "integrity": "sha512-7aelVrYqCLuVjq2kEKRTH8fXPTC0xKTkM+G7UlFkEwCXY3sFbSxvY375JoFowOAYbkaU47SrBvOefUlLZZ+6QA==", + "dev": true, + "optional": true, + "requires": { + "data-uri-to-buffer": "1.2.0", + "debug": "2.6.9", + "extend": "3.0.1", + "file-uri-to-path": "1.0.0", + "ftp": "0.3.10", + "readable-stream": "2.3.3" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -3431,53 +3972,17 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, "requires": { "glob-parent": "2.0.0", "is-glob": "2.0.1" - }, - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - } } }, "glob-parent": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, "requires": { "is-glob": "2.0.1" - }, - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - } } }, "globals": { @@ -3487,16 +3992,25 @@ "dev": true }, "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", "dev": true, "requires": { "array-union": "1.0.2", + "dir-glob": "2.0.0", "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" + "ignore": "3.3.7", + "pify": "3.0.0", + "slash": "1.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } } }, "globule": { @@ -3644,19 +4158,19 @@ "ansi-regex": "2.1.1" } }, - "has-binary": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.7.tgz", - "integrity": "sha1-aOYesWIQyVRaClzOBqhzkS/h5ow=", + "has-binary2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.2.tgz", + "integrity": "sha1-6D26SfC5vk0CbSc2U1DZ8D9Uvpg=", "dev": true, "requires": { - "isarray": "0.0.1" + "isarray": "2.0.1" }, "dependencies": { "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", "dev": true } } @@ -3678,6 +4192,66 @@ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, "hash-base": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", @@ -3714,6 +4288,17 @@ "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", "dev": true }, + "hipchat-notifier": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hipchat-notifier/-/hipchat-notifier-1.1.0.tgz", + "integrity": "sha1-ttJJdVQ3wZEII2d5nTupoPI7Ix4=", + "dev": true, + "optional": true, + "requires": { + "lodash": "4.17.4", + "request": "2.81.0" + } + }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -3730,15 +4315,6 @@ "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" }, - "homedir-polyfill": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", - "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", - "dev": true, - "requires": { - "parse-passwd": "1.0.0" - } - }, "hosted-git-info": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", @@ -3751,17 +4327,11 @@ "dev": true, "requires": { "inherits": "2.0.3", - "obuf": "1.1.1", + "obuf": "1.1.2", "readable-stream": "2.3.3", - "wbuf": "1.7.2" + "wbuf": "1.7.3" } }, - "html-comment-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.1.tgz", - "integrity": "sha1-ZouTd26q5V696POtRkswekljYl4=", - "dev": true - }, "html-entities": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", @@ -3769,25 +4339,25 @@ "dev": true }, "html-minifier": { - "version": "3.5.7", - "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.7.tgz", - "integrity": "sha512-GISXn6oKDo7+gVpKOgZJTbHMCUI2TSGfpg/8jgencWhWJsvEmsvp3M8emX7QocsXsYznWloLib3OeSfeyb/ewg==", + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.12.tgz", + "integrity": "sha512-+N778qLf0RWBscD0TPGoYdeGNDZ0s76/0pQhY1/409EOudcENkm9IbSkk37RDyPdg/09GVHTKotU4ya93RF1Gg==", "dev": true, "requires": { "camel-case": "3.0.0", - "clean-css": "4.1.9", - "commander": "2.12.2", + "clean-css": "4.1.11", + "commander": "2.15.1", "he": "1.1.1", "ncname": "1.0.0", "param-case": "2.1.1", "relateurl": "0.2.7", - "uglify-js": "3.2.1" + "uglify-js": "3.3.16" }, "dependencies": { "commander": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", - "integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "dev": true } } @@ -3799,7 +4369,7 @@ "dev": true, "requires": { "bluebird": "3.5.1", - "html-minifier": "3.5.7", + "html-minifier": "3.5.12", "loader-utils": "0.2.17", "lodash": "4.17.4", "pretty-error": "2.1.1", @@ -3882,9 +4452,15 @@ "depd": "1.1.1", "inherits": "2.0.3", "setprototypeof": "1.0.3", - "statuses": "1.3.1" + "statuses": "1.4.0" }, "dependencies": { + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", + "dev": true + }, "setprototypeof": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", @@ -3894,9 +4470,9 @@ } }, "http-parser-js": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.9.tgz", - "integrity": "sha1-6hoE+2St/wJC6ZdPKX3Uw8rSceE=", + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.11.tgz", + "integrity": "sha512-QCR5O2AjjMW8Mo4HyI1ctFcv+O99j/0g367V3YoVnrNw5hkDvAWZD0lWGcc+F4yN3V55USPCVix4efb75HxFfA==", "dev": true }, "http-proxy": { @@ -3909,6 +4485,17 @@ "requires-port": "1.0.0" } }, + "http-proxy-agent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-1.0.0.tgz", + "integrity": "sha1-zBzjjkU7+YSg93AtLdWcc9CBKEo=", + "dev": true, + "requires": { + "agent-base": "2.1.1", + "debug": "2.6.9", + "extend": "3.0.1" + } + }, "http-proxy-middleware": { "version": "0.17.4", "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.17.4.tgz", @@ -3921,6 +4508,12 @@ "micromatch": "2.3.11" }, "dependencies": { + "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-glob": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", @@ -3942,6 +4535,22 @@ "sshpk": "1.13.1" } }, + "httpntlm": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", + "integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", + "dev": true, + "requires": { + "httpreq": "0.4.24", + "underscore": "1.7.0" + } + }, + "httpreq": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.24.tgz", + "integrity": "sha1-QzX/2CzZaWaKOUZckprGHWOTYn8=", + "dev": true + }, "https-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", @@ -3964,55 +4573,10 @@ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" }, - "icss-replace-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", - "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", - "dev": true - }, - "icss-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz", - "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", - "dev": true, - "requires": { - "postcss": "6.0.14" - }, - "dependencies": { - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } - }, - "postcss": { - "version": "6.0.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz", - "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==", - "dev": true, - "requires": { - "chalk": "2.3.0", - "source-map": "0.6.1", - "supports-color": "4.5.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, "ieee754": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", - "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.10.tgz", + "integrity": "sha512-byWFX8OyW/qeVxcY21r6Ncxl0ZYHgnf0cPup2h34eHXrCJbOp7IuqnJ4Q0omfyWl6Z++BTI6bByf31pZt7iRLg==", "dev": true }, "iferr": { @@ -4021,6 +4585,12 @@ "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", "dev": true }, + "ignore": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", + "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", + "dev": true + }, "image-size": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", @@ -4035,9 +4605,9 @@ "dev": true }, "import-local": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-0.1.1.tgz", - "integrity": "sha1-sReVcqrNwRxqkQCftDDbyrX2aKg=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", + "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", "dev": true, "requires": { "pkg-dir": "2.0.0", @@ -4063,18 +4633,19 @@ "repeating": "2.0.1" } }, - "indexes-of": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", - "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", - "dev": true - }, "indexof": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", "dev": true }, + "inflection": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.10.0.tgz", + "integrity": "sha1-W//LEZetPoEFD44X4hZoCH7p6y8=", + "dev": true, + "optional": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -4111,9 +4682,9 @@ "dev": true }, "invariant": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", - "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", "dev": true, "requires": { "loose-envify": "1.3.1" @@ -4131,16 +4702,27 @@ "dev": true }, "ipaddr.js": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.5.2.tgz", - "integrity": "sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A=", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", + "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=", "dev": true }, - "is-absolute-url": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", - "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", - "dev": true + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } }, "is-arrayish": { "version": "0.2.1", @@ -4151,7 +4733,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, "requires": { "binary-extensions": "1.11.0" } @@ -4159,8 +4740,7 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "is-builtin-module": { "version": "1.0.0", @@ -4176,12 +4756,48 @@ "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", "dev": true }, - "is-date-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", "dev": true }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, "is-directory": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", @@ -4191,14 +4807,12 @@ "is-dotfile": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" }, "is-equal-shallow": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true, "requires": { "is-primitive": "2.0.0" } @@ -4206,14 +4820,12 @@ "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" }, "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 + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" }, "is-finite": { "version": "1.0.2", @@ -4232,21 +4844,26 @@ } }, "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "requires": { - "is-extglob": "2.1.1" + "is-extglob": "1.0.0" } }, + "is-my-ip-valid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", + "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==" + }, "is-my-json-valid": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", - "integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==", + "version": "2.17.2", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz", + "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==", "requires": { "generate-function": "2.0.0", "generate-object-property": "1.2.0", + "is-my-ip-valid": "1.0.0", "jsonpointer": "4.0.1", "xtend": "4.0.1" } @@ -4255,11 +4872,27 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, "requires": { "kind-of": "3.2.2" } }, + "is-odd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", + "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", + "dev": true, + "requires": { + "is-number": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, "is-path-cwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", @@ -4267,29 +4900,23 @@ "dev": true }, "is-path-in-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", - "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", "dev": true, "requires": { - "is-path-inside": "1.0.0" + "is-path-inside": "1.0.1" } }, "is-path-inside": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", - "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", "dev": true, "requires": { "path-is-inside": "1.0.2" } }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true - }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -4297,19 +4924,25 @@ "dev": true, "requires": { "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } } }, "is-posix-bracket": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" }, "is-primitive": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" }, "is-property": { "version": "1.0.2", @@ -4331,15 +4964,6 @@ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, - "is-svg": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz", - "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=", - "dev": true, - "requires": { - "html-comment-regex": "1.1.1" - } - }, "is-symbol": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", @@ -4356,6 +4980,12 @@ "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, "is-wsl": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", @@ -4379,10 +5009,12 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } }, "isstream": { "version": "0.1.2", @@ -4390,87 +5022,97 @@ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, "istanbul-api": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.2.1.tgz", - "integrity": "sha512-oFCwXvd65amgaPCzqrR+a2XjanS1MvpXN6l/MlMUTv6uiA1NOgGX+I0uyq8Lg3GDxsxPsaP1049krz3hIJ5+KA==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.1.tgz", + "integrity": "sha512-duj6AlLcsWNwUpfyfHt0nWIeRiZpuShnP40YTxOGQgtaN8fd6JYSxsvxUphTDy8V5MfDXo4s/xVCIIvVCO808g==", "dev": true, "requires": { "async": "2.6.0", + "compare-versions": "3.1.0", "fileset": "2.0.3", - "istanbul-lib-coverage": "1.1.1", - "istanbul-lib-hook": "1.1.0", - "istanbul-lib-instrument": "1.9.1", - "istanbul-lib-report": "1.1.2", - "istanbul-lib-source-maps": "1.2.2", - "istanbul-reports": "1.1.3", - "js-yaml": "3.7.0", + "istanbul-lib-coverage": "1.2.0", + "istanbul-lib-hook": "1.2.0", + "istanbul-lib-instrument": "1.10.1", + "istanbul-lib-report": "1.1.4", + "istanbul-lib-source-maps": "1.2.4", + "istanbul-reports": "1.3.0", + "js-yaml": "3.11.0", "mkdirp": "0.5.1", "once": "1.4.0" } }, "istanbul-instrumenter-loader": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-2.0.0.tgz", - "integrity": "sha1-5UkpAKsLuoNe+oAkywC+mz7qJwA=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.0.tgz", + "integrity": "sha512-alLSEFX06ApU75sm5oWcaVNaiss/bgMRiWTct3g0P0ZZTKjR+6QiCcuVOKDI1kWJgwHEnIXsv/dWm783kPpmtw==", "dev": true, "requires": { "convert-source-map": "1.5.1", - "istanbul-lib-instrument": "1.9.1", - "loader-utils": "0.2.17", - "object-assign": "4.1.1" + "istanbul-lib-instrument": "1.10.1", + "loader-utils": "1.1.0", + "schema-utils": "0.3.0" }, "dependencies": { - "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "dev": true, "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1", - "object-assign": "4.1.1" + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "schema-utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", + "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", + "dev": true, + "requires": { + "ajv": "5.5.2" } } } }, "istanbul-lib-coverage": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.1.tgz", - "integrity": "sha512-0+1vDkmzxqJIn5rcoEqapSB4DmPxE31EtI2dF2aCkV5esN9EWHxZ0dwgDClivMXJqE7zaYQxq30hj5L0nlTN5Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz", + "integrity": "sha512-GvgM/uXRwm+gLlvkWHTjDAvwynZkL9ns15calTrmhGgowlwJBbWMYzWbKqE2DT6JDP1AFXKa+Zi0EkqNCUqY0A==", "dev": true }, "istanbul-lib-hook": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.1.0.tgz", - "integrity": "sha512-U3qEgwVDUerZ0bt8cfl3dSP3S6opBoOtk3ROO5f2EfBr/SRiD9FQqzwaZBqFORu8W7O0EXpai+k7kxHK13beRg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.0.tgz", + "integrity": "sha512-p3En6/oGkFQV55Up8ZPC2oLxvgSxD8CzA0yBrhRZSh3pfv3OFj9aSGVC0yoerAi/O4u7jUVnOGVX1eVFM+0tmQ==", "dev": true, "requires": { "append-transform": "0.4.0" } }, "istanbul-lib-instrument": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.9.1.tgz", - "integrity": "sha512-RQmXeQ7sphar7k7O1wTNzVczF9igKpaeGQAG9qR2L+BS4DCJNTI9nytRmIVYevwO0bbq+2CXvJmYDuz0gMrywA==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.1.tgz", + "integrity": "sha512-1dYuzkOCbuR5GRJqySuZdsmsNKPL3PTuyPevQfoCXJePT9C8y1ga75neU+Tuy9+yS3G/dgx8wgOmp2KLpgdoeQ==", "dev": true, "requires": { - "babel-generator": "6.26.0", + "babel-generator": "6.26.1", "babel-template": "6.26.0", "babel-traverse": "6.26.0", "babel-types": "6.26.0", "babylon": "6.18.0", - "istanbul-lib-coverage": "1.1.1", + "istanbul-lib-coverage": "1.2.0", "semver": "5.4.1" } }, "istanbul-lib-report": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.2.tgz", - "integrity": "sha512-UTv4VGx+HZivJQwAo1wnRwe1KTvFpfi/NYwN7DcsrdzMXwpRT/Yb6r4SBPoHWj4VuQPakR32g4PUUeyKkdDkBA==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.4.tgz", + "integrity": "sha512-Azqvq5tT0U09nrncK3q82e/Zjkxa4tkFZv7E6VcqP0QCPn6oNljDPfrZEC/umNXds2t7b8sRJfs6Kmpzt8m2kA==", "dev": true, "requires": { - "istanbul-lib-coverage": "1.1.1", + "istanbul-lib-coverage": "1.2.0", "mkdirp": "0.5.1", "path-parse": "1.0.5", "supports-color": "3.2.3" @@ -4494,13 +5136,13 @@ } }, "istanbul-lib-source-maps": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.2.tgz", - "integrity": "sha512-8BfdqSfEdtip7/wo1RnrvLpHVEd8zMZEDmOFEnpC6dg0vXflHt9nvoAyQUzig2uMSXfF2OBEYBV3CVjIL9JvaQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.4.tgz", + "integrity": "sha512-UzuK0g1wyQijiaYQxj/CdNycFhAd2TLtO2obKQMTZrZ1jzEMRY3rvpASEKkaxbRR6brvdovfA03znPa/pXcejg==", "dev": true, "requires": { "debug": "3.1.0", - "istanbul-lib-coverage": "1.1.1", + "istanbul-lib-coverage": "1.2.0", "mkdirp": "0.5.1", "rimraf": "2.6.2", "source-map": "0.5.7" @@ -4518,30 +5160,27 @@ } }, "istanbul-reports": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.1.3.tgz", - "integrity": "sha512-ZEelkHh8hrZNI5xDaKwPMFwDsUf5wIEI2bXAFGp1e6deR2mnEKBPhLJEgr4ZBt8Gi6Mj38E/C8kcy9XLggVO2Q==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.3.0.tgz", + "integrity": "sha512-y2Z2IMqE1gefWUaVjrBm0mSKvUkaBy9Vqz8iwr/r40Y9hBbIteH5wqHG/9DLTfJ9xUnUT2j7A3+VVJ6EaYBllA==", "dev": true, "requires": { "handlebars": "4.0.11" } }, "jasmine": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz", - "integrity": "sha1-awicChFXax8W3xG4AUbZHU6Lij4=", - "dev": true, + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.1.0.tgz", + "integrity": "sha1-K9Wf1+xuwOistk4J9Fpo7SrRlSo=", "requires": { - "exit": "0.1.2", "glob": "7.1.2", - "jasmine-core": "2.8.0" + "jasmine-core": "3.1.0" } }, "jasmine-core": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz", - "integrity": "sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=", - "dev": true + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.1.0.tgz", + "integrity": "sha1-pHheE11d9lAk38kiSVPfWFvSdmw=" }, "jasmine-spec-reporter": { "version": "4.2.1", @@ -4559,9 +5198,9 @@ "dev": true }, "js-base64": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.3.2.tgz", - "integrity": "sha512-Y2/+DnfJJXT1/FCwUebUhLWb3QihxiSC42+ctHLGogmW2jPY6LCapMdFZXRvVP2z6qyKW7s6qncE/9gSqZiArw==" + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.3.tgz", + "integrity": "sha512-H7ErYLM34CvDMto3GbD6xD0JLUGYXR3QTcH6B/tr4Hi/QpSThnCsIp+Sy5FRTw3B0d6py4HcNkW7nO/wdtGWEw==" }, "js-tokens": { "version": "3.0.2", @@ -4570,13 +5209,13 @@ "dev": true }, "js-yaml": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz", - "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", + "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", "dev": true, "requires": { "argparse": "1.0.9", - "esprima": "2.7.3" + "esprima": "4.0.0" } }, "jsbn": { @@ -4586,9 +5225,9 @@ "optional": true }, "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", "dev": true }, "json-loader": { @@ -4605,8 +5244,7 @@ "json-schema-traverse": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" }, "json-stable-stringify": { "version": "1.0.1", @@ -4712,9 +5350,9 @@ } }, "karma": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/karma/-/karma-1.7.1.tgz", - "integrity": "sha512-k5pBjHDhmkdaUccnC7gE3mBzZjcxyxYsYVaqiL2G5AqlfLyBO5nw2VdNK+O16cveEPd/gIOWULH7gkiYYwVNHg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/karma/-/karma-2.0.2.tgz", + "integrity": "sha1-TS25QChQpmVR+nhLAWT7CCTtjEs=", "dev": true, "requires": { "bluebird": "3.5.1", @@ -4722,8 +5360,8 @@ "chokidar": "1.7.0", "colors": "1.1.2", "combine-lists": "1.0.1", - "connect": "3.6.5", - "core-js": "2.5.2", + "connect": "3.6.6", + "core-js": "2.5.5", "di": "0.0.1", "dom-serialize": "2.2.1", "expand-braces": "0.1.2", @@ -4731,25 +5369,25 @@ "graceful-fs": "4.1.11", "http-proxy": "1.16.2", "isbinaryfile": "3.0.2", - "lodash": "3.10.1", - "log4js": "0.6.38", - "mime": "1.4.1", + "lodash": "4.17.4", + "log4js": "2.5.3", + "mime": "1.6.0", "minimatch": "3.0.4", "optimist": "0.6.1", - "qjobs": "1.1.5", + "qjobs": "1.2.0", "range-parser": "1.2.0", "rimraf": "2.6.2", "safe-buffer": "5.1.1", - "socket.io": "1.7.3", - "source-map": "0.5.7", - "tmp": "0.0.31", + "socket.io": "2.0.4", + "source-map": "0.6.1", + "tmp": "0.0.33", "useragent": "2.2.1" }, "dependencies": { - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true } } @@ -4774,12 +5412,12 @@ } }, "karma-coverage-istanbul-reporter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-1.3.0.tgz", - "integrity": "sha1-0ULNnFVzHJ42Pvc3To7xoxvr+ts=", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-1.4.2.tgz", + "integrity": "sha512-sQHexslLF+QHzaKfK8+onTYMyvSwv+p5cDayVxhpEELGa3z0QuB+l0IMsicIkkBNMOJKQaqueiRoW7iuo7lsog==", "dev": true, "requires": { - "istanbul-api": "1.2.1", + "istanbul-api": "1.3.1", "minimatch": "3.0.4" } }, @@ -4790,9 +5428,9 @@ "dev": true }, "karma-jasmine-html-reporter": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-0.2.2.tgz", - "integrity": "sha1-SKjl7xiAdhfuK14zwRlMNbQ5Ukw=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.0.0.tgz", + "integrity": "sha512-SN9R/Pl9cY40yLlc7FkTcfswUr19M6ZZ25eM8X5wtZ0gvp0gneWZbe5lPYcer/Yrbz0D6QUiTSJaEzr3KBPvSg==", "dev": true, "requires": { "karma-jasmine": "1.1.1" @@ -4817,7 +5455,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -4828,9 +5465,9 @@ "integrity": "sha512-IdC4Hpp+mx53zTt6VAGsAtbGM0g4BV9fP8tTcviCosSwocHcRDw9uG5Rnv6wLWckF4r72qeXFoK9NkvV1gUJCQ==" }, "lazy-cache": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz", - "integrity": "sha1-f+3fLctu23fRHvHRF6tf/fCrG2U=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", "dev": true }, "lcid": { @@ -4847,10 +5484,10 @@ "integrity": "sha512-KPdIJKWcEAb02TuJtaLrhue0krtRLoRoo7x6BNJIBelO00t/CCdJQUnHW5V34OnHMWzIktSalJxRO+FvytQlCQ==", "dev": true, "requires": { - "errno": "0.1.4", + "errno": "0.1.7", "graceful-fs": "4.1.11", "image-size": "0.5.5", - "mime": "1.4.1", + "mime": "1.6.0", "mkdirp": "0.5.1", "promise": "7.3.1", "request": "2.81.0", @@ -4858,28 +5495,70 @@ } }, "less-loader": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-4.0.5.tgz", - "integrity": "sha1-rhVadAbKxqzSk9eFWH/P8PR4xN0=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-4.1.0.tgz", + "integrity": "sha512-KNTsgCE9tMOM70+ddxp9yyt9iHqgmSs0yTZc5XH5Wo+g80RWRIYNqE58QJKm/yMud5wZEvz50ugRDuzVIkyahg==", "dev": true, "requires": { - "clone": "2.1.1", + "clone": "2.1.2", "loader-utils": "1.1.0", - "pify": "2.3.0" + "pify": "3.0.0" }, "dependencies": { - "clone": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "optional": true, + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "libbase64": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", + "integrity": "sha1-YjUag5VjrF/1vSbxL2Dpgwu3UeY=", + "dev": true + }, + "libmime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", + "integrity": "sha1-UaGp50SOy9Ms2lRCFnW7IbwJPaY=", + "dev": true, + "requires": { + "iconv-lite": "0.4.15", + "libbase64": "0.1.0", + "libqp": "1.1.0" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", + "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=", "dev": true } } }, + "libqp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", + "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=", + "dev": true + }, "license-webpack-plugin": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-1.1.1.tgz", - "integrity": "sha512-TjKOyiC0exqd4Idy/4M8/DETR22dXBZks387DuS5LbslxHiMRXGx/Q2F/j9IUtvEoH5uFvt72vRgk/G6f8j3Dg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-1.3.1.tgz", + "integrity": "sha512-NqAFodJdpBUuf1iD+Ij8hQvF0rCFKlO2KaieoQzAPhFgzLCtJnC7Z7x5gQbGNjoe++wOKAtAmwVEIBLqq2Yp1A==", "dev": true, "requires": { "ejs": "2.5.7" @@ -4959,27 +5638,15 @@ "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" }, - "lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", - "dev": true - }, "lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true - }, "lodash.mergewith": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz", - "integrity": "sha1-FQzwoWeR9ZA7iJHqsVRgknS96lU=" + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", + "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==" }, "lodash.tail": { "version": "4.1.1", @@ -4987,118 +5654,279 @@ "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=", "dev": true }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", - "dev": true - }, "log4js": { - "version": "0.6.38", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-0.6.38.tgz", - "integrity": "sha1-LElBFmldb7JUgJQ9P8hy5mKlIv0=", + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-2.5.3.tgz", + "integrity": "sha512-YL/qpTxYtK0iWWbuKCrevDZz5lh+OjyHHD+mICqpjnYGKdNRBvPeh/1uYjkKUemT1CSO4wwLOwphWMpKAnD9kw==", "dev": true, "requires": { - "readable-stream": "1.0.34", - "semver": "4.3.6" + "amqplib": "0.5.2", + "axios": "0.15.3", + "circular-json": "0.5.3", + "date-format": "1.2.0", + "debug": "3.1.0", + "hipchat-notifier": "1.1.0", + "loggly": "1.1.1", + "mailgun-js": "0.7.15", + "nodemailer": "2.7.2", + "redis": "2.8.0", + "semver": "5.4.1", + "slack-node": "0.2.0", + "streamroller": "0.7.0" }, "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "ms": "2.0.0" } - }, - "semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true } } }, - "loglevel": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.0.tgz", - "integrity": "sha1-rgyqVhERSYxboTcj1vtjHSQAOTQ=", - "dev": true - }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true - }, - "loose-envify": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", - "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "loggly": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/loggly/-/loggly-1.1.1.tgz", + "integrity": "sha1-Cg/B0/o6XsRP3HuJe+uipGlc6+4=", "dev": true, + "optional": true, "requires": { - "js-tokens": "3.0.2" - } - }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "requires": { - "currently-unhandled": "0.4.1", - "signal-exit": "3.0.2" - } - }, - "lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", - "dev": true - }, - "lru-cache": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", - "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" - } - }, - "macaddress": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/macaddress/-/macaddress-0.2.8.tgz", - "integrity": "sha1-WQTcU3w57G2+/q6QIycTX6hRHxI=", - "dev": true - }, + "json-stringify-safe": "5.0.1", + "request": "2.75.0", + "timespan": "2.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true, + "optional": true + }, + "caseless": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", + "dev": true, + "optional": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "optional": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "form-data": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.0.0.tgz", + "integrity": "sha1-bwrrrcxdoWwT4ezBETfYX5uIOyU=", + "dev": true, + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "har-validator": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "dev": true, + "optional": true, + "requires": { + "chalk": "1.1.3", + "commander": "2.11.0", + "is-my-json-valid": "2.17.2", + "pinkie-promise": "2.0.1" + } + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", + "dev": true, + "optional": true + }, + "qs": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz", + "integrity": "sha1-HPyyXBCpsrSDBT/zn138kjOQjP4=", + "dev": true, + "optional": true + }, + "request": { + "version": "2.75.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.75.0.tgz", + "integrity": "sha1-0rgmiihtoT6qXQGt9dGMyQ9lfZM=", + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "bl": "1.1.2", + "caseless": "0.11.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.0.0", + "har-validator": "2.0.6", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "node-uuid": "1.4.8", + "oauth-sign": "0.8.2", + "qs": "6.2.3", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.4.3" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true, + "optional": true + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true, + "optional": true + } + } + }, + "loglevel": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.1.tgz", + "integrity": "sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=", + "dev": true + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "requires": { + "currently-unhandled": "0.4.1", + "signal-exit": "3.0.2" + } + }, + "lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", + "dev": true + }, + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, "magic-string": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.4.tgz", - "integrity": "sha512-kxBL06p6iO2qPBHsqGK2b3cRwiRGpnmSuVWNhwHcMX7qJOUr1HvricYP1LZOCdkQBUp0jiWg2d6WJwR3vYgByw==", + "version": "0.22.5", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.5.tgz", + "integrity": "sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w==", "dev": true, "requires": { "vlq": "0.2.3" } }, + "mailcomposer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-4.0.1.tgz", + "integrity": "sha1-DhxEsqB890DuF9wUm6AJ8Zyt/rQ=", + "dev": true, + "optional": true, + "requires": { + "buildmail": "4.0.1", + "libmime": "3.0.0" + } + }, + "mailgun-js": { + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/mailgun-js/-/mailgun-js-0.7.15.tgz", + "integrity": "sha1-7jZqINrGTDwVwD1sGz4O15UlKrs=", + "dev": true, + "optional": true, + "requires": { + "async": "2.1.5", + "debug": "2.2.0", + "form-data": "2.1.4", + "inflection": "1.10.0", + "is-stream": "1.1.0", + "path-proxy": "1.0.0", + "proxy-agent": "2.0.0", + "q": "1.4.1", + "tsscmp": "1.0.5" + }, + "dependencies": { + "async": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/async/-/async-2.1.5.tgz", + "integrity": "sha1-5YfGhYCZSsZ/xW/4bTrFa9voELw=", + "dev": true, + "optional": true, + "requires": { + "lodash": "4.17.4" + } + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "optional": true, + "requires": { + "ms": "0.7.1" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true, + "optional": true + } + } + }, "make-dir": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.1.0.tgz", - "integrity": "sha512-0Pkui4wLJ7rxvmfUvs87skoEaxmu0hCUApF8nonzpl7q//FWp9zu8W61Scz4sd/kUiqDxvUhtoam2efDyiBzcA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.2.0.tgz", + "integrity": "sha512-aNUAa4UMg/UougV25bbrU4ZaaKNjJ/3/xnvg/twpmKROPdKZPZ9wGgI0opdZzO8q/zUFawoUuixuOv33eZ61Iw==", "dev": true, "requires": { "pify": "3.0.0" @@ -5113,9 +5941,15 @@ } }, "make-error": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.0.tgz", - "integrity": "sha1-Uq06M5zPEM5itAQLcI/nByRLi5Y=", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz", + "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==", + "dev": true + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, "map-obj": { @@ -5123,16 +5957,32 @@ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "1.0.1" + } + }, "markdown-it": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.0.tgz", - "integrity": "sha512-tNuOCCfunY5v5uhcO2AUMArvKAyKMygX8tfup/JrgnsDqcCATQsAExBq7o5Ml9iMmO82bk6jYNLj6khcrl0JGA==", + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.1.tgz", + "integrity": "sha512-CzzqSSNkFRUf9vlWvhK1awpJreMRqdCrBvZ8DIoDWTOkESMIF741UPAhuAmbyWmdiFPA6WARNhnu2M6Nrhwa+A==", "requires": { "argparse": "1.0.9", "entities": "1.1.1", "linkify-it": "2.0.3", "mdurl": "1.0.1", - "uc.micro": "1.0.3" + "uc.micro": "1.0.5" + }, + "dependencies": { + "uc.micro": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.5.tgz", + "integrity": "sha512-JoLI4g5zv5qNyT09f4YAvEZIIV1oOjqnewYg5D38dkQljIzpPT296dbIGvKro3digYI1bkb7W6EP1y4uDlmzLg==" + } } }, "material-design-icons": { @@ -5140,23 +5990,6 @@ "resolved": "https://registry.npmjs.org/material-design-icons/-/material-design-icons-3.0.1.tgz", "integrity": "sha1-mnHEh0chjrylHlGmbaaCA4zct78=" }, - "math-expression-evaluator": { - "version": "1.2.17", - "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz", - "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=", - "dev": true - }, - "md5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", - "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", - "dev": true, - "requires": { - "charenc": "0.0.2", - "crypt": "0.0.2", - "is-buffer": "1.1.6" - } - }, "md5.js": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", @@ -5196,7 +6029,7 @@ "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", "dev": true, "requires": { - "mimic-fn": "1.1.0" + "mimic-fn": "1.2.0" } }, "memory-fs": { @@ -5205,7 +6038,7 @@ "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", "dev": true, "requires": { - "errno": "0.1.4", + "errno": "0.1.7", "readable-stream": "2.3.3" } }, @@ -5242,7 +6075,6 @@ "version": "2.3.11", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, "requires": { "arr-diff": "2.0.0", "array-unique": "0.2.1", @@ -5257,23 +6089,6 @@ "object.omit": "2.0.1", "parse-glob": "3.0.4", "regex-cache": "0.4.4" - }, - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - } } }, "miller-rabin": { @@ -5287,9 +6102,9 @@ } }, "mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "dev": true }, "mime-db": { @@ -5306,9 +6121,9 @@ } }, "mimic-fn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", - "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true }, "minimalistic-assert": { @@ -5337,23 +6152,44 @@ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "mississippi": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-1.3.0.tgz", - "integrity": "sha1-0gFYPrEjJ+PFwWQqQEqcrPlONPU=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz", + "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==", "dev": true, "requires": { - "concat-stream": "1.6.0", - "duplexify": "3.5.1", - "end-of-stream": "1.4.0", - "flush-write-stream": "1.0.2", + "concat-stream": "1.6.2", + "duplexify": "3.5.4", + "end-of-stream": "1.4.1", + "flush-write-stream": "1.0.3", "from2": "2.3.0", "parallel-transform": "1.1.0", - "pump": "1.0.3", - "pumpify": "1.3.5", + "pump": "2.0.1", + "pumpify": "1.4.0", "stream-each": "1.2.2", "through2": "2.0.3" } }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, + "requires": { + "for-in": "1.0.2", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, "mixin-object": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", @@ -5388,9 +6224,9 @@ } }, "moment": { - "version": "2.19.3", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.19.3.tgz", - "integrity": "sha1-vbmdJw1tf9p4zA+6zoVeJ/59pp8=" + "version": "2.22.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.1.tgz", + "integrity": "sha512-shJkRTSebXvsVqk56I+lkb2latjBs8I+pc2TzWc545y2iFnSjm7Wg0QMh+ZWcdSLQyGEau5jI8ocnmkyTgr9YQ==" }, "move-concurrently": { "version": "1.0.1", @@ -5413,13 +6249,13 @@ "dev": true }, "multicast-dns": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.1.tgz", - "integrity": "sha512-uV3/ckdsffHx9IrGQrx613mturMdMqQ06WTq+C09NsStJ9iNG6RcUWgPKs1Rfjy+idZT6tfQoXEusGNnEZhT3w==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", "dev": true, "requires": { - "dns-packet": "1.2.2", - "thunky": "0.1.0" + "dns-packet": "1.3.1", + "thunky": "1.0.2" } }, "multicast-dns-service-types": { @@ -5429,9 +6265,49 @@ "dev": true }, "nan": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", - "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=" + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" + }, + "nanomatch": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", + "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-odd": "2.0.0", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } }, "ncname": { "version": "1.0.0", @@ -5448,10 +6324,29 @@ "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", "dev": true }, + "neo-async": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.0.tgz", + "integrity": "sha512-nJmSswG4As/MkRq7QZFuH/sf/yuv8ODdMZrY4Bedjp77a5MK4A6s7YbBB64c9u79EBUOfXUXBvArmvzTD0X+6g==", + "dev": true + }, + "netmask": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", + "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=", + "dev": true, + "optional": true + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, "ng2-ace-editor": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/ng2-ace-editor/-/ng2-ace-editor-0.3.4.tgz", - "integrity": "sha512-U8WvJyx8kCpB3GhxGEInkIHhJzfe7p3KOnng+7o53HCGAjsbUDTLb//KgWKoLP5wM/ke5/kmP8OZuTjP39QkVg==", + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/ng2-ace-editor/-/ng2-ace-editor-0.3.7.tgz", + "integrity": "sha512-ddsLikPgQBzxr7bPR2DyPntBaOnsggF/1jqfIkEGPD99bhJvagcEnKjM8UYkGJdAJJ8TiZeH+FgNyiSabMqxbA==", "requires": { "ace-builds": "1.2.9", "brace": "0.10.0" @@ -5480,9 +6375,9 @@ } }, "node-forge": { - "version": "0.6.33", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.6.33.tgz", - "integrity": "sha1-RjgRh59XPUUVWtap9D3ClujoXrw=", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.1.tgz", + "integrity": "sha1-naYR6giYL0uUIGs760zJZl8gwwA=", "dev": true }, "node-gyp": { @@ -5532,7 +6427,7 @@ "console-browserify": "1.1.0", "constants-browserify": "1.0.0", "crypto-browserify": "3.12.0", - "domain-browser": "1.1.7", + "domain-browser": "1.2.0", "events": "1.1.1", "https-browserify": "1.0.0", "os-browserify": "0.3.0", @@ -5542,9 +6437,9 @@ "querystring-es3": "0.2.1", "readable-stream": "2.3.3", "stream-browserify": "2.0.1", - "stream-http": "2.7.2", + "stream-http": "2.8.1", "string_decoder": "1.0.3", - "timers-browserify": "2.0.4", + "timers-browserify": "2.0.6", "tty-browserify": "0.0.0", "url": "0.11.0", "util": "0.10.3", @@ -5558,9 +6453,9 @@ "dev": true }, "node-sass": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.7.2.tgz", - "integrity": "sha512-CaV+wLqZ7//Jdom5aUFCpGNoECd7BbNhjuwdsX/LkXBrHl8eb1Wjw4HvWqcFvhr5KuNgAk8i/myf/MQ1YYeroA==", + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.0.tgz", + "integrity": "sha512-QFHfrZl6lqRU3csypwviz2XLgGNOoWQbo2GOvtsfQqOfL4cy1BtWnhx/XUeAO9LT3ahBzSRXcEO6DdvAH9DzSg==", "requires": { "async-foreach": "0.1.3", "chalk": "1.1.3", @@ -5571,10 +6466,10 @@ "in-publish": "2.0.0", "lodash.assign": "4.2.0", "lodash.clonedeep": "4.5.0", - "lodash.mergewith": "4.6.0", + "lodash.mergewith": "4.6.1", "meow": "3.7.0", "mkdirp": "0.5.1", - "nan": "2.8.0", + "nan": "2.10.0", "node-gyp": "3.6.2", "npmlog": "4.1.2", "request": "2.79.0", @@ -5612,7 +6507,7 @@ "requires": { "chalk": "1.1.3", "commander": "2.11.0", - "is-my-json-valid": "2.16.1", + "is-my-json-valid": "2.17.2", "pinkie-promise": "2.0.1" } }, @@ -5660,6 +6555,91 @@ } } }, + "nodemailer": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-2.7.2.tgz", + "integrity": "sha1-8kLmSa7q45tsftdA73sGHEBNMPk=", + "dev": true, + "optional": true, + "requires": { + "libmime": "3.0.0", + "mailcomposer": "4.0.1", + "nodemailer-direct-transport": "3.3.2", + "nodemailer-shared": "1.1.0", + "nodemailer-smtp-pool": "2.8.2", + "nodemailer-smtp-transport": "2.7.2", + "socks": "1.1.9" + }, + "dependencies": { + "socks": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.9.tgz", + "integrity": "sha1-Yo1+TQSRJDVEWsC25Fk3bLPm1pE=", + "dev": true, + "optional": true, + "requires": { + "ip": "1.1.5", + "smart-buffer": "1.1.15" + } + } + } + }, + "nodemailer-direct-transport": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/nodemailer-direct-transport/-/nodemailer-direct-transport-3.3.2.tgz", + "integrity": "sha1-6W+vuQNYVglH5WkBfZfmBzilCoY=", + "dev": true, + "optional": true, + "requires": { + "nodemailer-shared": "1.1.0", + "smtp-connection": "2.12.0" + } + }, + "nodemailer-fetch": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", + "integrity": "sha1-ecSQihwPXzdbc/6IjamCj23JY6Q=", + "dev": true + }, + "nodemailer-shared": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", + "integrity": "sha1-z1mU4v0mjQD1zw+nZ6CBae2wfsA=", + "dev": true, + "requires": { + "nodemailer-fetch": "1.6.0" + } + }, + "nodemailer-smtp-pool": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/nodemailer-smtp-pool/-/nodemailer-smtp-pool-2.8.2.tgz", + "integrity": "sha1-LrlNbPhXgLG0clzoU7nL1ejajHI=", + "dev": true, + "optional": true, + "requires": { + "nodemailer-shared": "1.1.0", + "nodemailer-wellknown": "0.1.10", + "smtp-connection": "2.12.0" + } + }, + "nodemailer-smtp-transport": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.2.tgz", + "integrity": "sha1-A9ccdjFPFKx9vHvwM6am0W1n+3c=", + "dev": true, + "optional": true, + "requires": { + "nodemailer-shared": "1.1.0", + "nodemailer-wellknown": "0.1.10", + "smtp-connection": "2.12.0" + } + }, + "nodemailer-wellknown": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", + "integrity": "sha1-WG24EB2zDLRDjrVGc3pBqtDPE9U=", + "dev": true + }, "nopt": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", @@ -5685,7 +6665,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, "requires": { "remove-trailing-separator": "1.1.0" } @@ -5696,18 +6675,6 @@ "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", "dev": true }, - "normalize-url": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", - "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", - "dev": true, - "requires": { - "object-assign": "4.1.1", - "prepend-http": "1.0.4", - "query-string": "4.3.4", - "sort-keys": "1.1.2" - } - }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -5770,37 +6737,118 @@ "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", "dev": true }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + } + } + }, "object-keys": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", "dev": true }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, "object.omit": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true, "requires": { "for-own": "0.1.5", "is-extendable": "0.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "3.0.1" }, "dependencies": { - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, - "requires": { - "for-in": "1.0.2" - } + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true } } }, "obuf": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.1.tgz", - "integrity": "sha1-EEEktsYCxnlogaBCVB0220OlJk4=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", "dev": true }, "on-finished": { @@ -5853,6 +6901,30 @@ } } }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "optional": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + }, + "dependencies": { + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true, + "optional": true + } + } + }, "options": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", @@ -5920,10 +6992,13 @@ "dev": true }, "p-limit": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", - "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=", - "dev": true + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", + "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", + "dev": true, + "requires": { + "p-try": "1.0.0" + } }, "p-locate": { "version": "2.0.0", @@ -5931,7 +7006,7 @@ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, "requires": { - "p-limit": "1.1.0" + "p-limit": "1.2.0" } }, "p-map": { @@ -5940,6 +7015,60 @@ "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", "dev": true }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "pac-proxy-agent": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-1.1.0.tgz", + "integrity": "sha512-QBELCWyLYPgE2Gj+4wUEiMscHrQ8nRPBzYItQNOHWavwBt25ohZHQC4qnd5IszdVVrFbLsQ+dPkm6eqdjJAmwQ==", + "dev": true, + "optional": true, + "requires": { + "agent-base": "2.1.1", + "debug": "2.6.9", + "extend": "3.0.1", + "get-uri": "2.0.1", + "http-proxy-agent": "1.0.0", + "https-proxy-agent": "1.0.0", + "pac-resolver": "2.0.0", + "raw-body": "2.3.2", + "socks-proxy-agent": "2.1.1" + } + }, + "pac-resolver": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-2.0.0.tgz", + "integrity": "sha1-mbiNLxk/ve78HJpSnB8yYKtSd80=", + "dev": true, + "optional": true, + "requires": { + "co": "3.0.6", + "degenerator": "1.0.4", + "ip": "1.0.1", + "netmask": "1.0.6", + "thunkify": "2.1.2" + }, + "dependencies": { + "co": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/co/-/co-3.0.6.tgz", + "integrity": "sha1-FEXyJsXrlWE45oyawwFn6n0ua9o=", + "dev": true, + "optional": true + }, + "ip": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.0.1.tgz", + "integrity": "sha1-x+NWzeoiWucbNtcPLnGpK6TkJZA=", + "dev": true, + "optional": true + } + } + }, "pako": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", @@ -5972,7 +7101,7 @@ "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", "dev": true, "requires": { - "asn1.js": "4.9.2", + "asn1.js": "4.10.1", "browserify-aes": "1.1.1", "create-hash": "1.1.3", "evp_bytestokey": "1.0.3", @@ -5983,29 +7112,11 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "dev": true, "requires": { "glob-base": "0.3.0", "is-dotfile": "1.0.3", "is-extglob": "1.0.0", "is-glob": "2.0.1" - }, - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - } } }, "parse-json": { @@ -6016,21 +7127,6 @@ "error-ex": "1.3.1" } }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "parsejson": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/parsejson/-/parsejson-0.0.3.tgz", - "integrity": "sha1-q343WfIJ7OmUN5c/fQ8fZK4OZKs=", - "dev": true, - "requires": { - "better-assert": "1.0.2" - } - }, "parseqs": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", @@ -6055,12 +7151,24 @@ "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", "dev": true }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, "path-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", "dev": true }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, "path-exists": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", @@ -6092,6 +7200,25 @@ "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", "dev": true }, + "path-proxy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-proxy/-/path-proxy-1.0.0.tgz", + "integrity": "sha1-GOijaFn8nS8aU7SN7hOFQ8Ag3l4=", + "dev": true, + "optional": true, + "requires": { + "inflection": "1.3.8" + }, + "dependencies": { + "inflection": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.3.8.tgz", + "integrity": "sha1-y9Fg2p91sUw8xjV41POWeEvzAU4=", + "dev": true, + "optional": true + } + } + }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -6118,7 +7245,7 @@ "create-hmac": "1.1.6", "ripemd160": "2.0.1", "safe-buffer": "5.1.1", - "sha.js": "2.4.9" + "sha.js": "2.4.11" } }, "performance-now": { @@ -6183,210 +7310,89 @@ } } }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "version": "6.0.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.21.tgz", + "integrity": "sha512-y/bKfbQz2Nn/QBC08bwvYUxEFOVGfPIUOTsJ2CK5inzlXW9SdYR1x4pEsG9blRAF/PX+wRNdOah+gx/hv4q7dw==", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.3.2", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "2.3.2", + "source-map": "0.6.1", + "supports-color": "5.3.0" }, "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", "dev": true, "requires": { - "ansi-styles": "2.2.1", + "ansi-styles": "3.2.1", "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } + "supports-color": "5.3.0" } }, "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "3.0.0" } } } }, - "postcss-calc": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz", - "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", + "postcss-import": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-11.1.0.tgz", + "integrity": "sha512-5l327iI75POonjxkXgdRCUS+AlzAdBx4pOvMEhTKTCjb1p8IEeVR9yx3cPbmN7LIWJLbfnIXxAhoB4jpD0c/Cw==", "dev": true, "requires": { - "postcss": "5.2.18", - "postcss-message-helpers": "2.0.0", - "reduce-css-calc": "1.3.0" + "postcss": "6.0.21", + "postcss-value-parser": "3.3.0", + "read-cache": "1.0.0", + "resolve": "1.5.0" } }, - "postcss-colormin": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-2.2.2.tgz", - "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=", + "postcss-load-config": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-1.2.0.tgz", + "integrity": "sha1-U56a/J3chiASHr+djDZz4M5Q0oo=", "dev": true, "requires": { - "colormin": "1.1.2", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "cosmiconfig": "2.2.2", + "object-assign": "4.1.1", + "postcss-load-options": "1.2.0", + "postcss-load-plugins": "2.3.0" } }, - "postcss-convert-values": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz", - "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=", + "postcss-load-options": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-load-options/-/postcss-load-options-1.2.0.tgz", + "integrity": "sha1-sJixVZ3awt8EvAuzdfmaXP4rbYw=", "dev": true, "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-custom-properties": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-6.2.0.tgz", - "integrity": "sha512-eNR2h9T9ciKMoQEORrPjH33XeN/nuvVuxArOKmHtsFbGbNss631tgTrKou3/pmjAZbA4QQkhLIkPQkIk3WW+8w==", - "dev": true, - "requires": { - "balanced-match": "1.0.0", - "postcss": "6.0.14" - }, - "dependencies": { - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } - }, - "postcss": { - "version": "6.0.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz", - "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==", - "dev": true, - "requires": { - "chalk": "2.3.0", - "source-map": "0.6.1", - "supports-color": "4.5.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "postcss-discard-comments": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz", - "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", - "dev": true, - "requires": { - "postcss": "5.2.18" - } - }, - "postcss-discard-duplicates": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz", - "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=", - "dev": true, - "requires": { - "postcss": "5.2.18" - } - }, - "postcss-discard-empty": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz", - "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", - "dev": true, - "requires": { - "postcss": "5.2.18" - } - }, - "postcss-discard-overridden": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz", - "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", - "dev": true, - "requires": { - "postcss": "5.2.18" - } - }, - "postcss-discard-unused": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz", - "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", - "dev": true, - "requires": { - "postcss": "5.2.18", - "uniqs": "2.0.0" - } - }, - "postcss-filter-plugins": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.2.tgz", - "integrity": "sha1-bYWGJTTXNaxCDkqFgG4fXUKG2Ew=", - "dev": true, - "requires": { - "postcss": "5.2.18", - "uniqid": "4.1.1" - } - }, - "postcss-load-config": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-1.2.0.tgz", - "integrity": "sha1-U56a/J3chiASHr+djDZz4M5Q0oo=", - "dev": true, - "requires": { - "cosmiconfig": "2.2.2", - "object-assign": "4.1.1", - "postcss-load-options": "1.2.0", - "postcss-load-plugins": "2.3.0" - } - }, - "postcss-load-options": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-load-options/-/postcss-load-options-1.2.0.tgz", - "integrity": "sha1-sJixVZ3awt8EvAuzdfmaXP4rbYw=", - "dev": true, - "requires": { - "cosmiconfig": "2.2.2", - "object-assign": "4.1.1" + "cosmiconfig": "2.2.2", + "object-assign": "4.1.1" } }, "postcss-load-plugins": { @@ -6400,426 +7406,28 @@ } }, "postcss-loader": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-2.0.9.tgz", - "integrity": "sha512-sgoXPtmgVT3aBAhU47Kig8oPF+mbXl8Unjvtz1Qj1q2D2EvSVJW2mKJNzxv5y/LvA9xWwuvdysvhc7Zn80UWWw==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-2.1.3.tgz", + "integrity": "sha512-RuBcNE8rjCkIB0IsbmkGFRmQJTeQJfCI88E0VTarPNTvaNSv9OFv1DvTwgtAN/qlzyiELsmmmtX/tEzKp/cdug==", "dev": true, "requires": { "loader-utils": "1.1.0", - "postcss": "6.0.14", + "postcss": "6.0.21", "postcss-load-config": "1.2.0", - "schema-utils": "0.3.0" - }, - "dependencies": { - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } - }, - "postcss": { - "version": "6.0.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz", - "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==", - "dev": true, - "requires": { - "chalk": "2.3.0", - "source-map": "0.6.1", - "supports-color": "4.5.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "postcss-merge-idents": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz", - "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", - "dev": true, - "requires": { - "has": "1.0.1", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-merge-longhand": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz", - "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=", - "dev": true, - "requires": { - "postcss": "5.2.18" - } - }, - "postcss-merge-rules": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz", - "integrity": "sha1-0d9d+qexrMO+VT8OnhDofGG19yE=", - "dev": true, - "requires": { - "browserslist": "1.7.7", - "caniuse-api": "1.6.1", - "postcss": "5.2.18", - "postcss-selector-parser": "2.2.3", - "vendors": "1.0.1" - } - }, - "postcss-message-helpers": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz", - "integrity": "sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4=", - "dev": true - }, - "postcss-minify-font-values": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz", - "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=", - "dev": true, - "requires": { - "object-assign": "4.1.1", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-minify-gradients": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz", - "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", - "dev": true, - "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-minify-params": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz", - "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=", - "dev": true, - "requires": { - "alphanum-sort": "1.0.2", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0", - "uniqs": "2.0.0" - } - }, - "postcss-minify-selectors": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz", - "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=", - "dev": true, - "requires": { - "alphanum-sort": "1.0.2", - "has": "1.0.1", - "postcss": "5.2.18", - "postcss-selector-parser": "2.2.3" - } - }, - "postcss-modules-extract-imports": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz", - "integrity": "sha1-thTJcgvmgW6u41+zpfqh26agXds=", - "dev": true, - "requires": { - "postcss": "6.0.14" - }, - "dependencies": { - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } - }, - "postcss": { - "version": "6.0.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz", - "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==", - "dev": true, - "requires": { - "chalk": "2.3.0", - "source-map": "0.6.1", - "supports-color": "4.5.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "postcss-modules-local-by-default": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", - "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", - "dev": true, - "requires": { - "css-selector-tokenizer": "0.7.0", - "postcss": "6.0.14" - }, - "dependencies": { - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } - }, - "postcss": { - "version": "6.0.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz", - "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==", - "dev": true, - "requires": { - "chalk": "2.3.0", - "source-map": "0.6.1", - "supports-color": "4.5.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "postcss-modules-scope": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", - "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", - "dev": true, - "requires": { - "css-selector-tokenizer": "0.7.0", - "postcss": "6.0.14" - }, - "dependencies": { - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } - }, - "postcss": { - "version": "6.0.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz", - "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==", - "dev": true, - "requires": { - "chalk": "2.3.0", - "source-map": "0.6.1", - "supports-color": "4.5.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "postcss-modules-values": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", - "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", - "dev": true, - "requires": { - "icss-replace-symbols": "1.1.0", - "postcss": "6.0.14" - }, - "dependencies": { - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } - }, - "postcss": { - "version": "6.0.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz", - "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==", - "dev": true, - "requires": { - "chalk": "2.3.0", - "source-map": "0.6.1", - "supports-color": "4.5.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "postcss-normalize-charset": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz", - "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", - "dev": true, - "requires": { - "postcss": "5.2.18" - } - }, - "postcss-normalize-url": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz", - "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=", - "dev": true, - "requires": { - "is-absolute-url": "2.1.0", - "normalize-url": "1.9.1", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-ordered-values": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz", - "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=", - "dev": true, - "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-reduce-idents": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz", - "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", - "dev": true, - "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-reduce-initial": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz", - "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", - "dev": true, - "requires": { - "postcss": "5.2.18" - } - }, - "postcss-reduce-transforms": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz", - "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", - "dev": true, - "requires": { - "has": "1.0.1", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-selector-parser": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", - "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", - "dev": true, - "requires": { - "flatten": "1.0.2", - "indexes-of": "1.0.1", - "uniq": "1.0.1" - } - }, - "postcss-svgo": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz", - "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=", - "dev": true, - "requires": { - "is-svg": "2.1.0", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0", - "svgo": "0.7.2" - } - }, - "postcss-unique-selectors": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz", - "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=", - "dev": true, - "requires": { - "alphanum-sort": "1.0.2", - "postcss": "5.2.18", - "uniqs": "2.0.0" + "schema-utils": "0.4.5" } }, "postcss-url": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/postcss-url/-/postcss-url-7.3.0.tgz", - "integrity": "sha512-VBP6uf6iL3AZra23nkPkOEkS/5azj1xf/toRrjfkolfFEgg9Gyzg9UhJZeIsz12EGKZTNVeGbPa2XtaZm/iZvg==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/postcss-url/-/postcss-url-7.3.1.tgz", + "integrity": "sha512-Ya5KIjGptgz0OtrVYfi2UbLxVAZ6Emc4Of+Grx4Sf1deWlRpFwLr8FrtkUxfqh+XiZIVkXbjQrddE10ESpNmdA==", "dev": true, "requires": { - "mime": "1.4.1", + "mime": "1.6.0", "minimatch": "3.0.4", "mkdirp": "0.5.1", - "postcss": "6.0.14", - "xxhashjs": "0.2.1" - }, - "dependencies": { - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } - }, - "postcss": { - "version": "6.0.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz", - "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==", - "dev": true, - "requires": { - "chalk": "2.3.0", - "source-map": "0.6.1", - "supports-color": "4.5.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } + "postcss": "6.0.21", + "xxhashjs": "0.2.2" } }, "postcss-value-parser": { @@ -6828,28 +7436,16 @@ "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=", "dev": true }, - "postcss-zindex": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz", - "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", - "dev": true, - "requires": { - "has": "1.0.1", - "postcss": "5.2.18", - "uniqs": "2.0.0" - } - }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, "preserve": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" }, "pretty-error": { "version": "2.1.1", @@ -6889,12 +7485,12 @@ "dev": true }, "protractor": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/protractor/-/protractor-5.2.1.tgz", - "integrity": "sha512-oasutUD/4WUAZdQRo6EtWlVmvgwxWCkcc49XaTiETRPDffRoj8JAQg6gpv42aiP+qyUuK6qJS/XYNBI4Me44Gw==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/protractor/-/protractor-5.3.1.tgz", + "integrity": "sha512-AW9qJ0prx2QEMy1gnhJ1Sl1WBQL2R3fx/VnG09FEmWprPIQPK14t0B83OB/pAGddpxiDCAAV0KiNNLf2c2Y/lQ==", "dev": true, "requires": { - "@types/node": "6.0.92", + "@types/node": "6.0.106", "@types/q": "0.0.32", "@types/selenium-webdriver": "2.53.43", "blocking-proxy": "1.0.1", @@ -6912,9 +7508,9 @@ }, "dependencies": { "@types/node": { - "version": "6.0.92", - "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.92.tgz", - "integrity": "sha512-awEYSSTn7dauwVCYSx2CJaPTu0Z1Ht2oR1b2AD3CYao6ZRb+opb6EL43fzmD7eMFgMHzTBWSUzlWSD+S8xN0Nw==", + "version": "6.0.106", + "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.106.tgz", + "integrity": "sha512-U4Zv5fx7letrisRv6HgSSPSY00FZM4NMIkilt+IAExvQLuNa6jYVwCKcnSs2NqTN4+KDl9PskvcCiMce9iePCA==", "dev": true }, "adm-zip": { @@ -6950,7 +7546,7 @@ "requires": { "globby": "5.0.0", "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.0", + "is-path-in-cwd": "1.0.1", "object-assign": "4.1.1", "pify": "2.3.0", "pinkie-promise": "2.0.1", @@ -6971,10 +7567,21 @@ "pinkie-promise": "2.0.1" } }, - "q": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", - "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", + "jasmine": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz", + "integrity": "sha1-awicChFXax8W3xG4AUbZHU6Lij4=", + "dev": true, + "requires": { + "exit": "0.1.2", + "glob": "7.1.2", + "jasmine-core": "2.8.0" + } + }, + "jasmine-core": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz", + "integrity": "sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=", "dev": true }, "supports-color": { @@ -7005,19 +7612,45 @@ } }, "proxy-addr": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.2.tgz", - "integrity": "sha1-ZXFQT0e7mI7IGAJT+F3X4UlSvew=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", + "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==", "dev": true, "requires": { "forwarded": "0.1.2", - "ipaddr.js": "1.5.2" + "ipaddr.js": "1.6.0" + } + }, + "proxy-agent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-2.0.0.tgz", + "integrity": "sha1-V+tTR6qAXXTsaByyVknbo5yTNJk=", + "dev": true, + "optional": true, + "requires": { + "agent-base": "2.1.1", + "debug": "2.6.9", + "extend": "3.0.1", + "http-proxy-agent": "1.0.0", + "https-proxy-agent": "1.0.0", + "lru-cache": "2.6.5", + "pac-proxy-agent": "1.1.0", + "socks-proxy-agent": "2.1.1" + }, + "dependencies": { + "lru-cache": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.6.5.tgz", + "integrity": "sha1-5W1jVBSO3o13B7WNFDIg/QjfD9U=", + "dev": true, + "optional": true + } } }, "prr": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz", - "integrity": "sha1-GoS4WQgyVQFBGFPQCB7j+obikmo=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", "dev": true }, "pseudomap": { @@ -7035,28 +7668,28 @@ "browserify-rsa": "4.0.1", "create-hash": "1.1.3", "parse-asn1": "5.1.0", - "randombytes": "2.0.5" + "randombytes": "2.0.6" } }, "pump": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", - "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", "dev": true, "requires": { - "end-of-stream": "1.4.0", + "end-of-stream": "1.4.1", "once": "1.4.0" } }, "pumpify": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.3.5.tgz", - "integrity": "sha1-G2ccYZlAq8rqwK0OOjwWS+dgmTs=", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.4.0.tgz", + "integrity": "sha512-2kmNR9ry+Pf45opRVirpNuIFotsxUGLaYqxIwuR77AYrYRMuFCz9eryHBS52L360O+NcR383CL4QYlMKPq4zYA==", "dev": true, "requires": { - "duplexify": "3.5.1", + "duplexify": "3.5.4", "inherits": "2.0.3", - "pump": "1.0.3" + "pump": "2.0.1" } }, "punycode": { @@ -7065,15 +7698,15 @@ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" }, "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", "dev": true }, "qjobs": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.1.5.tgz", - "integrity": "sha1-ZZ3p8s+NzCehSBJ28gU3cnI4LnM=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", "dev": true }, "qs": { @@ -7081,16 +7714,6 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=" }, - "query-string": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", - "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", - "dev": true, - "requires": { - "object-assign": "4.1.1", - "strict-uri-encode": "1.1.0" - } - }, "querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", @@ -7113,7 +7736,6 @@ "version": "1.1.7", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", - "dev": true, "requires": { "is-number": "3.0.0", "kind-of": "4.0.0" @@ -7123,7 +7745,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, "requires": { "kind-of": "3.2.2" }, @@ -7132,7 +7753,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -7143,7 +7763,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -7151,21 +7770,21 @@ } }, "randombytes": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz", - "integrity": "sha512-8T7Zn1AhMsQ/HI1SjcCfT/t4ii3eAqco3yOcSzS4mozsOz69lHLsoMXmF9nZgnFanYscnSlUSgs8uZyKzpE6kg==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", "dev": true, "requires": { "safe-buffer": "5.1.1" } }, "randomfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.3.tgz", - "integrity": "sha512-YL6GrhrWoic0Eq8rXVbMptH7dAxCs0J+mh5Y0euNekPPYaxEmdVGim6GdoxoRzKW2yJoU8tueifS7mYxvcFDEQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", "dev": true, "requires": { - "randombytes": "2.0.5", + "randombytes": "2.0.6", "safe-buffer": "5.1.1" } }, @@ -7176,9 +7795,9 @@ "dev": true }, "raven-js": { - "version": "3.20.1", - "resolved": "https://registry.npmjs.org/raven-js/-/raven-js-3.20.1.tgz", - "integrity": "sha512-Wr973Ipmd+dWUPQ6mSru/gyteavriEyP6G3iDZ2jpI3sBAWejtVtoXO5BHujEWB1z+/dqCLn+Zezgdc30xZcVA==" + "version": "3.24.2", + "resolved": "https://registry.npmjs.org/raven-js/-/raven-js-3.24.2.tgz", + "integrity": "sha512-Dy/FHDxuo5pXywVf8Nrs5utB2juMATpkxWGqHjVbpFD3m8CaWYLvkB5SEXjWFUZ5GvUsrBVVQ+Dfcp0x6Z7SOg==" }, "raw-body": { "version": "2.3.2", @@ -7198,6 +7817,15 @@ "integrity": "sha1-DD0L6u2KAclm2Xh793goElKpeao=", "dev": true }, + "read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", + "dev": true, + "requires": { + "pify": "2.3.0" + } + }, "read-pkg": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", @@ -7235,7 +7863,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "minimatch": "3.0.4", @@ -7252,46 +7879,36 @@ "strip-indent": "1.0.1" } }, - "reduce-css-calc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", - "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", + "redis": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", + "integrity": "sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==", "dev": true, + "optional": true, "requires": { - "balanced-match": "0.4.2", - "math-expression-evaluator": "1.2.17", - "reduce-function-call": "1.0.2" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - } + "double-ended-queue": "2.1.0-0", + "redis-commands": "1.3.5", + "redis-parser": "2.6.0" } }, - "reduce-function-call": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.2.tgz", - "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=", + "redis-commands": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.3.5.tgz", + "integrity": "sha512-foGF8u6MXGFF++1TZVC6icGXuMYPftKXt1FBT2vrfU9ZATNtZJ8duRC5d1lEfE8hyVe3jhelHGB91oB7I6qLsA==", "dev": true, - "requires": { - "balanced-match": "0.4.2" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - } - } + "optional": true + }, + "redis-parser": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz", + "integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=", + "dev": true, + "optional": true }, "reflect-metadata": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.10.tgz", - "integrity": "sha1-tPg3BEFqytiZiMmxVjXUfgO5NEo=", + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.12.tgz", + "integrity": "sha512-n+IyV+nGz3+0q3/Yf1ra12KpCyi001bi4XFxSjbiWWjfqb52iTTtpGXmCCAOWWIAn9KEuFZKGqBERHmrtScZ3A==", "dev": true }, "regenerate": { @@ -7301,20 +7918,29 @@ "dev": true }, "regenerator-runtime": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz", - "integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", "dev": true }, "regex-cache": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", - "dev": true, "requires": { "is-equal-shallow": "0.1.3" } }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" + } + }, "regexpu-core": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", @@ -7339,6 +7965,14 @@ "dev": true, "requires": { "jsesc": "0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } } }, "relateurl": { @@ -7350,8 +7984,7 @@ "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" }, "renderkid": { "version": "2.0.1", @@ -7377,14 +8010,12 @@ "repeat-element": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", - "dev": true + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=" }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, "repeating": { "version": "2.0.1", @@ -7423,6 +8054,28 @@ "uuid": "3.1.0" } }, + "requestretry": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/requestretry/-/requestretry-1.13.0.tgz", + "integrity": "sha512-Lmh9qMvnQXADGAQxsXHP4rbgO6pffCfuR8XUBdP9aitJcLQJxhp7YZK4xAVYXnPJ5E52mwrfiKQtKonPL8xsmg==", + "dev": true, + "optional": true, + "requires": { + "extend": "3.0.1", + "lodash": "4.17.4", + "request": "2.81.0", + "when": "3.7.8" + }, + "dependencies": { + "when": { + "version": "3.7.8", + "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", + "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=", + "dev": true, + "optional": true + } + } + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -7469,6 +8122,18 @@ "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", "dev": true }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, "right-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", @@ -7511,9 +8176,9 @@ "integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=" }, "rxjs": { - "version": "5.5.5", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.5.tgz", - "integrity": "sha512-D/MfQnPMBk8P8gfwGxvCkuaWBcG58W7dUMT//URPoYzIbDEKT0GezdirkK5whMgKFBATfCoTpxO8bJQGJ04W5A==", + "version": "5.5.10", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.10.tgz", + "integrity": "sha512-SRjimIDUHJkon+2hFo7xnvNC4ZEHGzCRwh9P7nzX3zPkCGFEg/tuElrNR7L/rZMagnK2JeH2jQwPRpmyXyLB6A==", "requires": { "symbol-observable": "1.0.1" } @@ -7523,6 +8188,15 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "0.1.15" + } + }, "sass-graph": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", @@ -7535,15 +8209,15 @@ } }, "sass-loader": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-6.0.6.tgz", - "integrity": "sha512-c3/Zc+iW+qqDip6kXPYLEgsAu2lf4xz0EZDplB7EmSUMda12U1sGJPetH55B/j9eu0bTtKzKlNPWWyYC7wFNyQ==", + "version": "6.0.7", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-6.0.7.tgz", + "integrity": "sha512-JoiyD00Yo1o61OJsoP2s2kb19L1/Y2p3QFcCdWdF6oomBGKVYuZyqHWemRBfQ2uGYsk+CH3eCguXNfpjzlcpaA==", "dev": true, "requires": { - "async": "2.6.0", - "clone-deep": "0.3.0", + "clone-deep": "2.0.2", "loader-utils": "1.1.0", "lodash.tail": "4.1.1", + "neo-async": "2.5.0", "pify": "3.0.0" }, "dependencies": { @@ -7565,18 +8239,19 @@ } }, "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz", + "integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=", "dev": true }, "schema-utils": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", - "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz", + "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==", "dev": true, "requires": { - "ajv": "5.5.1" + "ajv": "6.3.0", + "ajv-keywords": "3.1.0" } }, "scss-tokenizer": { @@ -7584,7 +8259,7 @@ "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", "requires": { - "js-base64": "2.3.2", + "js-base64": "2.4.3", "source-map": "0.4.4" }, "dependencies": { @@ -7628,12 +8303,12 @@ } }, "selfsigned": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.1.tgz", - "integrity": "sha1-v4y3uDJWxFUeMTR8YxF3jbme7FI=", + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.2.tgz", + "integrity": "sha1-tESVgNmZKbZbEKSDiTAaZZIIh1g=", "dev": true, "requires": { - "node-forge": "0.6.33" + "node-forge": "0.7.1" } }, "semver": { @@ -7650,16 +8325,24 @@ "semver": "5.4.1" } }, + "semver-intersect": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.3.1.tgz", + "integrity": "sha1-j6hKnhAovSOeRTDRo+GB5pjYhLo=", + "requires": { + "semver": "5.4.1" + } + }, "send": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz", - "integrity": "sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A==", + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", "dev": true, "requires": { "debug": "2.6.9", - "depd": "1.1.1", + "depd": "1.1.2", "destroy": "1.0.4", - "encodeurl": "1.0.1", + "encodeurl": "1.0.2", "escape-html": "1.0.3", "etag": "1.8.1", "fresh": "0.5.2", @@ -7668,16 +8351,30 @@ "ms": "2.0.0", "on-finished": "2.3.0", "range-parser": "1.2.0", - "statuses": "1.3.1" + "statuses": "1.4.0" + }, + "dependencies": { + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "dev": true + } } }, + "serialize-javascript": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.4.0.tgz", + "integrity": "sha1-fJWFFNtqwkQ6irwGLcn3iGp/YAU=", + "dev": true + }, "serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", "dev": true, "requires": { - "accepts": "1.3.4", + "accepts": "1.3.5", "batch": "0.6.1", "debug": "2.6.9", "escape-html": "1.0.3", @@ -7687,15 +8384,15 @@ } }, "serve-static": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz", - "integrity": "sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", "dev": true, "requires": { - "encodeurl": "1.0.1", + "encodeurl": "1.0.2", "escape-html": "1.0.3", "parseurl": "1.3.2", - "send": "0.16.1" + "send": "0.16.2" } }, "set-blocking": { @@ -7706,8 +8403,30 @@ "set-immediate-shim": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", - "dev": true + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=" + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } }, "setimmediate": { "version": "1.0.5", @@ -7722,9 +8441,9 @@ "dev": true }, "sha.js": { - "version": "2.4.9", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.9.tgz", - "integrity": "sha512-G8zektVqbiPHrylgew9Zg1VRB1L/DtXNUVAM6q4QLy8NE3qtHlFXTf8VLL4k1Yl6c7NMjtZUTdXV+X44nFaT6A==", + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, "requires": { "inherits": "2.0.3", @@ -7732,25 +8451,21 @@ } }, "shallow-clone": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-0.1.2.tgz", - "integrity": "sha1-WQnodLp3EG1zrEFM/sH/yofZcGA=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-1.0.0.tgz", + "integrity": "sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==", "dev": true, "requires": { "is-extendable": "0.1.1", - "kind-of": "2.0.1", - "lazy-cache": "0.2.7", + "kind-of": "5.1.0", "mixin-object": "2.0.1" }, "dependencies": { "kind-of": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", - "integrity": "sha1-AY7HpM5+OobLkUG+UZ0kyPqpgbU=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true } } }, @@ -7780,175 +8495,256 @@ "integrity": "sha1-IglwbxyFCp8dENDYQJGLRvJuG8k=", "dev": true, "requires": { - "debug": "2.6.9" + "debug": "2.6.9" + } + }, + "slack-node": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/slack-node/-/slack-node-0.2.0.tgz", + "integrity": "sha1-3kuN3aqLeT9h29KTgQT9q/N9+jA=", + "dev": true, + "optional": true, + "requires": { + "requestretry": "1.13.0" } }, - "sntp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "smart-buffer": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-1.1.15.tgz", + "integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY=", + "dev": true + }, + "smtp-connection": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz", + "integrity": "sha1-1275EnyyPCJZ7bHoNJwujV4tdME=", + "dev": true, "requires": { - "hoek": "2.16.3" + "httpntlm": "1.6.1", + "nodemailer-shared": "1.1.0" } }, - "socket.io": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-1.7.3.tgz", - "integrity": "sha1-uK+cq6AJSeVo42nxMn6pvp6iRhs=", + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", "dev": true, "requires": { - "debug": "2.3.3", - "engine.io": "1.8.3", - "has-binary": "0.1.7", - "object-assign": "4.1.0", - "socket.io-adapter": "0.5.0", - "socket.io-client": "1.7.3", - "socket.io-parser": "2.3.1" + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.1", + "use": "3.1.0" }, "dependencies": { - "debug": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz", - "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "ms": "0.7.2" + "is-descriptor": "0.1.6" } }, - "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", - "dev": true + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } }, - "object-assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz", - "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=", + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", "dev": true } } }, - "socket.io-adapter": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-0.5.0.tgz", - "integrity": "sha1-y21LuL7IHhB4uZZ3+c7QBGBmu4s=", + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, "requires": { - "debug": "2.3.3", - "socket.io-parser": "2.3.1" + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" }, "dependencies": { - "debug": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz", - "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "ms": "0.7.2" + "is-descriptor": "1.0.2" } }, - "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true } } }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "requires": { + "hoek": "2.16.3" + } + }, + "socket.io": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.0.4.tgz", + "integrity": "sha1-waRZDO/4fs8TxyZS8Eb3FrKeYBQ=", + "dev": true, + "requires": { + "debug": "2.6.9", + "engine.io": "3.1.5", + "socket.io-adapter": "1.1.1", + "socket.io-client": "2.0.4", + "socket.io-parser": "3.1.3" + } + }, + "socket.io-adapter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", + "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", + "dev": true + }, "socket.io-client": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-1.7.3.tgz", - "integrity": "sha1-sw6GqhDV7zVGYBwJzeR2Xjgdo3c=", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.4.tgz", + "integrity": "sha1-CRilUkBtxeVAs4Dc2Xr8SmQzL44=", "dev": true, "requires": { "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", "component-bind": "1.0.0", "component-emitter": "1.2.1", - "debug": "2.3.3", - "engine.io-client": "1.8.3", - "has-binary": "0.1.7", + "debug": "2.6.9", + "engine.io-client": "3.1.6", + "has-cors": "1.1.0", "indexof": "0.0.1", "object-component": "0.0.3", + "parseqs": "0.0.5", "parseuri": "0.0.5", - "socket.io-parser": "2.3.1", + "socket.io-parser": "3.1.3", "to-array": "0.1.4" - }, - "dependencies": { - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true - }, - "debug": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz", - "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", - "dev": true, - "requires": { - "ms": "0.7.2" - } - }, - "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", - "dev": true - } } }, "socket.io-parser": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.3.1.tgz", - "integrity": "sha1-3VMgJRA85Clpcya+/WQAX8/ltKA=", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.1.3.tgz", + "integrity": "sha512-g0a2HPqLguqAczs3dMECuA1RgoGFPyvDqcbaDEdCWY9g59kdUAz3YRmaJBNKXflrHNwB7Q12Gkf/0CZXfdHR7g==", "dev": true, "requires": { - "component-emitter": "1.1.2", - "debug": "2.2.0", - "isarray": "0.0.1", - "json3": "3.3.2" + "component-emitter": "1.2.1", + "debug": "3.1.0", + "has-binary2": "1.0.2", + "isarray": "2.0.1" }, "dependencies": { "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { - "ms": "0.7.1" + "ms": "2.0.0" } }, "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", "dev": true } } }, "sockjs": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.18.tgz", - "integrity": "sha1-2bKJMWyn33dZXvKZ4HXw+TfrQgc=", + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz", + "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==", "dev": true, "requires": { "faye-websocket": "0.10.0", - "uuid": "2.0.3" - }, - "dependencies": { - "uuid": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", - "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", - "dev": true - } + "uuid": "3.1.0" } }, "sockjs-client": { @@ -7976,13 +8772,25 @@ } } }, - "sort-keys": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", - "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "socks": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.10.tgz", + "integrity": "sha1-W4t/x8jzQcU+0FbpKbe/Tei6e1o=", "dev": true, "requires": { - "is-plain-obj": "1.1.0" + "ip": "1.1.5", + "smart-buffer": "1.1.15" + } + }, + "socks-proxy-agent": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-2.1.1.tgz", + "integrity": "sha512-sFtmYqdUK5dAMh85H0LEVFUCO7OhJJe1/z2x/Z6mxp3s7/QPf1RkZmpZy+BpuU0bEjcV9npqKjq9Y3kwFUjnxw==", + "dev": true, + "requires": { + "agent-base": "2.1.1", + "extend": "3.0.1", + "socks": "1.1.10" } }, "source-list-map": { @@ -7994,38 +8802,19 @@ "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" }, - "source-map-loader": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-0.2.3.tgz", - "integrity": "sha512-MYbFX9DYxmTQFfy2v8FC1XZwpwHKYxg3SK8Wb7VPBKuhDjz8gi9re2819MsG4p49HDyiOSUKlmZ+nQBArW5CGw==", + "source-map-resolve": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", + "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", "dev": true, "requires": { - "async": "2.6.0", - "loader-utils": "0.2.17", - "source-map": "0.6.1" - }, - "dependencies": { - "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "dev": true, - "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1", - "object-assign": "4.1.1" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } + "atob": "2.0.3", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" } }, "source-map-support": { @@ -8037,6 +8826,12 @@ "source-map": "0.5.7" } }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, "spdx-correct": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", @@ -8066,22 +8861,31 @@ "http-deceiver": "1.2.7", "safe-buffer": "5.1.1", "select-hose": "2.0.0", - "spdy-transport": "2.0.20" + "spdy-transport": "2.1.0" } }, "spdy-transport": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.0.20.tgz", - "integrity": "sha1-c15yBUxIayNU/onnAiVgBKOazk0=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.1.0.tgz", + "integrity": "sha512-bpUeGpZcmZ692rrTiqf9/2EUakI6/kXX1Rpe0ib/DyOzbiexVfXkw6GnvI9hVGvIwVaUhkaBojjCZwLNRGQg1g==", "dev": true, "requires": { "debug": "2.6.9", "detect-node": "2.0.3", "hpack.js": "2.1.6", - "obuf": "1.1.1", + "obuf": "1.1.2", "readable-stream": "2.3.3", "safe-buffer": "5.1.1", - "wbuf": "1.7.2" + "wbuf": "1.7.3" + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2" } }, "sprintf-js": { @@ -8112,18 +8916,96 @@ } }, "ssri": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.0.0.tgz", - "integrity": "sha512-728D4yoQcQm1ooZvSbywLkV1RjfITZXh0oWrhM/lnsx3nAHx7LsRGJWB/YyvoceAYRq98xqbstiN4JBv1/wNHg==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", + "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", "dev": true, "requires": { "safe-buffer": "5.1.1" } }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "0.2.5", + "object-copy": "0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, "statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", "dev": true }, "stdout-stream": { @@ -8150,14 +9032,14 @@ "integrity": "sha512-mc1dbFhGBxvTM3bIWmAAINbqiuAk9TATcfIQC8P+/+HJefgaiTlMn2dHvkX8qlI12KeYKSQ1Ua9RrIqrn1VPoA==", "dev": true, "requires": { - "end-of-stream": "1.4.0", + "end-of-stream": "1.4.1", "stream-shift": "1.0.0" } }, "stream-http": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz", - "integrity": "sha512-c0yTD2rbQzXtSsFSVhtpvY/vS6u066PcXOX9kBB3mSO76RiUQzL340uJkGBWnlBg4/HZzqiUXtaVA7wcRcJgEw==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.1.tgz", + "integrity": "sha512-cQ0jo17BLca2r0GfRdZKYAGLU6JRoIWxqSOakUMuKOT6MOK7AAlE856L33QuDmAy/eeOrhLee3dZKX0Uadu93A==", "dev": true, "requires": { "builtin-status-codes": "3.0.0", @@ -8173,11 +9055,28 @@ "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", "dev": true }, - "strict-uri-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", - "dev": true + "streamroller": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", + "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", + "dev": true, + "requires": { + "date-format": "1.2.0", + "debug": "3.1.0", + "mkdirp": "0.5.1", + "readable-stream": "2.3.3" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } }, "string-width": { "version": "1.0.2", @@ -8232,19 +9131,37 @@ "get-stdin": "4.0.1" } }, - "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=", - "dev": true - }, "style-loader": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.13.2.tgz", - "integrity": "sha1-dFMzhM9pjHEEx5URULSXF63C87s=", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.19.1.tgz", + "integrity": "sha512-IRE+ijgojrygQi3rsqT0U4dd+UcPCqcVvauZpCnQrGAlEe+FUIyrK93bUDScamesjP08JlQNsFJU+KmPedP5Og==", "dev": true, "requires": { - "loader-utils": "1.1.0" + "loader-utils": "1.1.0", + "schema-utils": "0.3.0" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "schema-utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", + "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", + "dev": true, + "requires": { + "ajv": "5.5.2" + } + } } }, "stylus": { @@ -8275,12 +9192,6 @@ "path-is-absolute": "1.0.1" } }, - "sax": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz", - "integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=", - "dev": true - }, "source-map": { "version": "0.1.43", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", @@ -8293,9 +9204,9 @@ } }, "stylus-loader": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-3.0.1.tgz", - "integrity": "sha1-d/SzT9Aw0lsmF7z1UT21sHMMQIk=", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-3.0.2.tgz", + "integrity": "sha512-+VomPdZ6a0razP+zinir61yZgpw2NfljeSsdUF5kJuEzlo3khXhY19Fn6l8QQz1GRJGtMCo8nG5C04ePyV7SUA==", "dev": true, "requires": { "loader-utils": "1.1.0", @@ -8312,21 +9223,6 @@ "has-flag": "2.0.0" } }, - "svgo": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.2.tgz", - "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=", - "dev": true, - "requires": { - "coa": "1.0.4", - "colors": "1.1.2", - "csso": "2.3.2", - "js-yaml": "3.7.0", - "mkdirp": "0.5.1", - "sax": "1.2.4", - "whet.extend": "0.9.9" - } - }, "symbol-observable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", @@ -8364,10 +9260,17 @@ "xtend": "4.0.1" } }, + "thunkify": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", + "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=", + "dev": true, + "optional": true + }, "thunky": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-0.1.0.tgz", - "integrity": "sha1-vzAUaCTituZ7Dy16Ssi+smkIaE4=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.2.tgz", + "integrity": "sha1-qGLgGOP7HqLsP85dVWBc9X8kc3E=", "dev": true }, "ticky": { @@ -8382,18 +9285,25 @@ "dev": true }, "timers-browserify": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.4.tgz", - "integrity": "sha512-uZYhyU3EX8O7HQP+J9fTVYwsq90Vr68xPEFo7yrVImIxYvHgukBEgOB/SgGoorWVTzGM/3Z+wUNnboA4M8jWrg==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.6.tgz", + "integrity": "sha512-HQ3nbYRAowdVd0ckGFvmJPPCOH/CHleFN/Y0YQCX1DVaB7t+KFvisuyN09fuP8Jtp1CpfSh8O8bMkHbdbPe6Pw==", "dev": true, "requires": { "setimmediate": "1.0.5" } }, + "timespan": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/timespan/-/timespan-2.3.0.tgz", + "integrity": "sha1-SQLOBAvRPYRcj1myfp1ZutbzmSk=", + "dev": true, + "optional": true + }, "tmp": { - "version": "0.0.31", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz", - "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=", + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "requires": { "os-tmpdir": "1.0.2" @@ -8417,6 +9327,48 @@ "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", "dev": true }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + } + } + }, "toposort": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.6.tgz", @@ -8471,51 +9423,92 @@ } }, "ts-node": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-3.3.0.tgz", - "integrity": "sha1-wTxqMCTjC+EYDdUwOPwgkonUv2k=", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-5.0.1.tgz", + "integrity": "sha512-XK7QmDcNHVmZkVtkiwNDWiERRHPyU8nBqZB1+iv2UhOG0q3RQ9HsZ2CMqISlFbxjrYFGfG2mX7bW4dAyxBVzUw==", "dev": true, "requires": { "arrify": "1.0.1", - "chalk": "2.2.2", - "diff": "3.4.0", - "make-error": "1.3.0", + "chalk": "2.3.2", + "diff": "3.5.0", + "make-error": "1.3.4", "minimist": "1.2.0", "mkdirp": "0.5.1", - "source-map-support": "0.4.18", - "tsconfig": "6.0.0", - "v8flags": "3.0.1", + "source-map-support": "0.5.4", "yn": "2.0.0" - } - }, - "tsconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-6.0.0.tgz", - "integrity": "sha1-aw6DdgA9evGGT434+J3QBZ/80DI=", - "dev": true, - "requires": { - "strip-bom": "3.0.0", - "strip-json-comments": "2.0.1" }, "dependencies": { - "strip-bom": { + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" + } + }, + "has-flag": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true + }, + "source-map-support": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.4.tgz", + "integrity": "sha512-PETSPG6BjY1AHs2t64vS2aqAgu6dMIMXJULWFBGbh2Gr8nVLbCFDo6i/RMMvviIQ2h1Z8+5gQhVKSn2je9nmdg==", + "dev": true, + "requires": { + "source-map": "0.6.1" + } + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } } } }, "tsickle": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/tsickle/-/tsickle-0.25.5.tgz", - "integrity": "sha512-CgOT/1WqOKtE1fyvqB+kTJ7bizE33xj1TyUIzGbxJBGCbQmknCrZbb35DtxMiK6pJo4CrPyoS8iGFddfHKtSNA==", + "version": "0.27.5", + "resolved": "https://registry.npmjs.org/tsickle/-/tsickle-0.27.5.tgz", + "integrity": "sha512-NP+CjM1EXza/M8mOXBLH3vkFEJiu1zfEAlC5WdJxHPn8l96QPz5eooP6uAgYtw1CcKfuSyIiheNUdKxtDWCNeg==", "dev": true, "requires": { "minimist": "1.2.0", "mkdirp": "0.5.1", - "source-map": "0.5.7", - "source-map-support": "0.4.18" + "source-map": "0.6.1", + "source-map-support": "0.5.5" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.5.tgz", + "integrity": "sha512-mR7/Nd5l1z6g99010shcXJiNEaf3fEtmLhRB/sBcQVJGodcHCULPp2y4Sfa43Kv2zq7T+Izmfp/WHCR6dYkQCA==", + "dev": true, + "requires": { + "buffer-from": "1.0.0", + "source-map": "0.6.1" + } + } } }, "tslib": { @@ -8524,31 +9517,81 @@ "integrity": "sha512-ymKWWZJST0/CkgduC2qkzjMOWr4bouhuURNXCn/inEX0L57BnRG6FhX76o7FOnsjHazCjfU2LKeSrlS2sIKQJg==" }, "tslint": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.8.0.tgz", - "integrity": "sha1-H0mtWy53x2w69N3K5VKuTjYS6xM=", + "version": "5.9.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.9.1.tgz", + "integrity": "sha1-ElX4ej/1frCw4fDmEKi0dIBGya4=", "dev": true, "requires": { "babel-code-frame": "6.26.0", "builtin-modules": "1.1.1", - "chalk": "2.2.2", - "commander": "2.11.0", - "diff": "3.4.0", + "chalk": "2.3.2", + "commander": "2.15.1", + "diff": "3.5.0", "glob": "7.1.2", + "js-yaml": "3.11.0", "minimatch": "3.0.4", "resolve": "1.5.0", "semver": "5.4.1", "tslib": "1.8.0", - "tsutils": "2.12.2" + "tsutils": "2.22.2" + }, + "dependencies": { + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" + } + }, + "commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } } }, + "tsscmp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", + "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=", + "dev": true, + "optional": true + }, "tsutils": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.12.2.tgz", - "integrity": "sha1-rVikhl0X7D3bZjG2ylO+FKVlb/M=", + "version": "2.22.2", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.22.2.tgz", + "integrity": "sha512-u06FUSulCJ+Y8a2ftuqZN6kIGqdP2yJjUPEngXqmdPND4UQfb04igcotH+dw+IFr417yP6muCLE8/5/Qlfnx0w==", "dev": true, "requires": { - "tslib": "1.8.0" + "tslib": "1.9.0" + }, + "dependencies": { + "tslib": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz", + "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==", + "dev": true + } } }, "tty-browserify": { @@ -8571,14 +9614,40 @@ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "optional": true }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2" + } + }, "type-is": { - "version": "1.6.15", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", - "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", "dev": true, "requires": { "media-typer": "0.3.0", - "mime-types": "2.1.17" + "mime-types": "2.1.18" + }, + "dependencies": { + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, + "requires": { + "mime-db": "1.33.0" + } + } } }, "typedarray": { @@ -8599,19 +9668,19 @@ "integrity": "sha1-ftUNXg+an7ClczeSWfKndFjVAZI=" }, "uglify-js": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.2.1.tgz", - "integrity": "sha512-BhZTJPmOKPSUcjnx2nlfaOQKHLyjjT4HFyzFWF1BUErx9knJNpdW94ql5o8qVxeNL+8IAWjEjnPvASH2yZnkMg==", + "version": "3.3.16", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.16.tgz", + "integrity": "sha512-FMh5SRqJRGhv9BbaTffENIpDDQIoPDR8DBraunGORGhySArsXlw9++CN+BWzPBLpoI4RcSnpfGPnilTxWL3Vvg==", "dev": true, "requires": { - "commander": "2.12.2", + "commander": "2.15.1", "source-map": "0.6.1" }, "dependencies": { "commander": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", - "integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "dev": true }, "source-map": { @@ -8630,24 +9699,25 @@ "optional": true }, "uglifyjs-webpack-plugin": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.1.2.tgz", - "integrity": "sha512-k07cmJTj+8vZMSc3BaQ9uW7qVl2MqDts4ti4KaNACXEcXSw2vQM2S8olSk/CODxvcSFGvUHzNSqA8JQlhgUJPw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.2.4.tgz", + "integrity": "sha512-z0IbjpW8b3O/OVn+TTZN4pI29RN1zktFBXLIzzfZ+++cUtZ1ERSlLWgpE/5OERuEUs1ijVQnpYAkSlpoVmQmSQ==", "dev": true, "requires": { - "cacache": "10.0.1", + "cacache": "10.0.4", "find-cache-dir": "1.0.0", - "schema-utils": "0.3.0", + "schema-utils": "0.4.5", + "serialize-javascript": "1.4.0", "source-map": "0.6.1", - "uglify-es": "3.2.1", + "uglify-es": "3.3.9", "webpack-sources": "1.1.0", - "worker-farm": "1.5.2" + "worker-farm": "1.6.0" }, "dependencies": { "commander": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", - "integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", "dev": true }, "source-map": { @@ -8657,44 +9727,64 @@ "dev": true }, "uglify-es": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.2.1.tgz", - "integrity": "sha512-c+Fy4VuGvPmT7mj7vEPjRR/iNFuXuOAkufhCtCvTGX0Hr4gCM9YwCnLgHkxr1ngqSODQaDObU3g8SF8uE/tY1w==", + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", + "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", "dev": true, "requires": { - "commander": "2.12.2", + "commander": "2.13.0", "source-map": "0.6.1" } } } }, "ultron": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", - "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", "dev": true }, - "uniq": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "underscore": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", "dev": true }, - "uniqid": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/uniqid/-/uniqid-4.1.1.tgz", - "integrity": "sha1-iSIN32t1GuUrX3JISGNShZa7hME=", + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", "dev": true, "requires": { - "macaddress": "0.2.8" + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + } + } } }, - "uniqs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", - "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", - "dev": true - }, "unique-filename": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.0.tgz", @@ -8725,12 +9815,70 @@ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", "dev": true }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "upath": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.0.4.tgz", + "integrity": "sha512-d4SJySNBXDaQp+DPrziv3xGS6w3d2Xt69FijJr86zMPBy23JEloMCEOUBBzuN7xCtjLCnmB9tI/z7SBCahHBOw==", + "dev": true + }, "upper-case": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", "dev": true }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, "url": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", @@ -8756,8 +9904,31 @@ "dev": true, "requires": { "loader-utils": "1.1.0", - "mime": "1.4.1", + "mime": "1.6.0", "schema-utils": "0.3.0" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "schema-utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", + "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", + "dev": true, + "requires": { + "ajv": "5.5.2" + } + } } }, "url-parse": { @@ -8778,6 +9949,23 @@ } } }, + "use": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", + "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, "useragent": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.2.1.tgz", @@ -8785,7 +9973,7 @@ "dev": true, "requires": { "lru-cache": "2.2.4", - "tmp": "0.0.31" + "tmp": "0.0.33" }, "dependencies": { "lru-cache": { @@ -8835,14 +10023,12 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" }, - "v8flags": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.0.1.tgz", - "integrity": "sha1-3Oj8N5wX2fLJ6e142JzgAFKxt2s=", - "dev": true, - "requires": { - "homedir-polyfill": "1.0.1" - } + "uws": { + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/uws/-/uws-9.14.0.tgz", + "integrity": "sha512-HNMztPP5A1sKuVFmdZ6BPVpBQd5bUjNC8EFMFiICK+oho/OQsAJy5hnIx4btMHiOk8j04f/DbIlqnEZ9d72dqg==", + "dev": true, + "optional": true }, "validate-npm-package-license": { "version": "3.0.1", @@ -8859,12 +10045,6 @@ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", "dev": true }, - "vendors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.1.tgz", - "integrity": "sha1-N61zyO5Bf7PVgOeFMSMH0nSEfyI=", - "dev": true - }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", @@ -8909,20 +10089,343 @@ "integrity": "sha1-sM01KhpQ9RVWNCD/1YYflQ8dhbg=" }, "watchpack": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.4.0.tgz", - "integrity": "sha1-ShRyvLuVK9Cpu0A2gB+VTfs5+qw=", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.5.0.tgz", + "integrity": "sha512-RSlipNQB1u48cq0wH/BNfCu1tD/cJ8ydFIkNYhp9o+3d+8unClkIovpW5qpFPgmL9OE48wfAnlZydXByWP82AA==", "dev": true, "requires": { - "async": "2.6.0", - "chokidar": "1.7.0", - "graceful-fs": "4.1.11" + "chokidar": "2.0.2", + "graceful-fs": "4.1.11", + "neo-async": "2.5.0" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "3.1.10", + "normalize-path": "2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.1.tgz", + "integrity": "sha512-SO5lYHA3vO6gz66erVvedSCkp7AKWdv6VcQ2N4ysXfPxdAlxAMMAdwegGGcv1Bqwm7naF1hNdk5d6AAIEHV2nQ==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "define-property": "1.0.0", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "kind-of": "6.0.2", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "chokidar": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.2.tgz", + "integrity": "sha512-l32Hw3wqB0L2kGVmSbK/a+xXLDrUEsc84pSgMkmwygHvD7ubRsP/vxxHa5BtB6oix1XLLVCHyYMsckRXxThmZw==", + "dev": true, + "requires": { + "anymatch": "2.0.0", + "async-each": "1.0.1", + "braces": "2.3.1", + "glob-parent": "3.1.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "4.0.0", + "normalize-path": "2.1.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0", + "upath": "1.0.4" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "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-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.1", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.9", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + } } }, "wbuf": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.2.tgz", - "integrity": "sha1-1pe5nx9ZUS3ydRvkJ2nBWAtYAf4=", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", "dev": true, "requires": { "minimalistic-assert": "1.0.0" @@ -8953,7 +10456,7 @@ "adm-zip": "0.4.4", "rimraf": "2.6.2", "tmp": "0.0.24", - "ws": "1.1.2", + "ws": "1.1.5", "xml2js": "0.4.4" } }, @@ -8963,6 +10466,22 @@ "integrity": "sha1-1qXhmNFKmDXMby18PZ4wJCjIzxI=", "dev": true }, + "ultron": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", + "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=", + "dev": true + }, + "ws": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz", + "integrity": "sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==", + "dev": true, + "requires": { + "options": "0.0.6", + "ultron": "1.0.2" + } + }, "xml2js": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.4.tgz", @@ -8970,21 +10489,21 @@ "dev": true, "requires": { "sax": "0.6.1", - "xmlbuilder": "9.0.4" + "xmlbuilder": "9.0.7" } } } }, "webpack": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.10.0.tgz", - "integrity": "sha512-fxxKXoicjdXNUMY7LIdY89tkJJJ0m1Oo8PQutZ5rLgWbV5QVKI15Cn7+/IHnRTd3vfKfiwBx6SBqlorAuNA8LA==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.11.0.tgz", + "integrity": "sha512-3kOFejWqj5ISpJk4Qj/V7w98h9Vl52wak3CLiw/cDOfbVTq7FeoZ0SdoHHY9PYlHr50ZS42OfvzE2vB4nncKQg==", "dev": true, "requires": { - "acorn": "5.2.1", + "acorn": "5.5.3", "acorn-dynamic-import": "2.0.2", - "ajv": "5.5.1", - "ajv-keywords": "2.1.1", + "ajv": "6.3.0", + "ajv-keywords": "3.1.0", "async": "2.6.0", "enhanced-resolve": "3.4.1", "escope": "3.6.0", @@ -9000,7 +10519,7 @@ "supports-color": "4.5.0", "tapable": "0.2.8", "uglifyjs-webpack-plugin": "0.4.6", - "watchpack": "1.4.0", + "watchpack": "1.5.0", "webpack-sources": "1.1.0", "yargs": "8.0.2" }, @@ -9195,96 +10714,44 @@ "cliui": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wrap-ansi": "2.1.0" - }, - "dependencies": { - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - } - } - } - } - }, - "yargs-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", - "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", - "dev": true, - "requires": { - "camelcase": "4.1.0" - }, - "dependencies": { - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - } - } - } - } - }, - "webpack-concat-plugin": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/webpack-concat-plugin/-/webpack-concat-plugin-1.4.2.tgz", - "integrity": "sha512-HdV2xOq4twtL2ThR9NSCCQ888v1JBMpJfm3k2mA1I5LkS2+/6rv8q/bb9yTSaR0fVaMtANZi4Wkz0xc33MAt6w==", - "dev": true, - "requires": { - "md5": "2.2.1", - "uglify-js": "2.8.29" - }, - "dependencies": { - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, - "requires": { - "center-align": "0.1.3", - "right-align": "0.1.3", - "wordwrap": "0.0.2" - } - }, - "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", - "dev": true, - "requires": { - "source-map": "0.5.7", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + } } }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", "dev": true, "requires": { - "camelcase": "1.2.1", - "cliui": "2.1.0", - "decamelize": "1.2.0", - "window-size": "0.1.0" + "camelcase": "4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + } } } } @@ -9327,57 +10794,130 @@ "path-is-absolute": "1.0.1", "range-parser": "1.2.0", "time-stamp": "2.0.0" - }, - "dependencies": { - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - } } }, "webpack-dev-server": { - "version": "2.9.7", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-2.9.7.tgz", - "integrity": "sha512-Pu7uoQFgQj5RE5wmlfkpYSzihMKxulwEuO2xCsaMnAnyRSApwoVi3B8WCm9XbigyWTHaIMzYGkB90Vr6leAeTQ==", + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-2.11.2.tgz", + "integrity": "sha512-zrPoX97bx47vZiAXfDrkw8pe9QjJ+lunQl3dypojyWwWr1M5I2h0VSrMPfTjopHQPRNn+NqfjcMmhoLcUJe2gA==", "dev": true, "requires": { "ansi-html": "0.0.7", "array-includes": "3.0.3", "bonjour": "3.5.0", - "chokidar": "1.7.0", - "compression": "1.7.1", + "chokidar": "2.0.2", + "compression": "1.7.2", "connect-history-api-fallback": "1.5.0", "debug": "3.1.0", "del": "3.0.0", - "express": "4.16.2", + "express": "4.16.3", "html-entities": "1.2.1", "http-proxy-middleware": "0.17.4", - "import-local": "0.1.1", + "import-local": "1.0.0", "internal-ip": "1.2.0", "ip": "1.1.5", "killable": "1.0.0", - "loglevel": "1.6.0", + "loglevel": "1.6.1", "opn": "5.1.0", "portfinder": "1.0.13", - "selfsigned": "1.10.1", + "selfsigned": "1.10.2", "serve-index": "1.9.1", - "sockjs": "0.3.18", + "sockjs": "0.3.19", "sockjs-client": "1.1.4", "spdy": "3.4.7", "strip-ansi": "3.0.1", - "supports-color": "4.5.0", + "supports-color": "5.3.0", "webpack-dev-middleware": "1.12.2", "yargs": "6.6.0" }, "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "3.1.10", + "normalize-path": "2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.1.tgz", + "integrity": "sha512-SO5lYHA3vO6gz66erVvedSCkp7AKWdv6VcQ2N4ysXfPxdAlxAMMAdwegGGcv1Bqwm7naF1hNdk5d6AAIEHV2nQ==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "define-property": "1.0.0", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "kind-of": "6.0.2", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, "camelcase": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", "dev": true }, + "chokidar": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.2.tgz", + "integrity": "sha512-l32Hw3wqB0L2kGVmSbK/a+xXLDrUEsc84pSgMkmwygHvD7ubRsP/vxxHa5BtB6oix1XLLVCHyYMsckRXxThmZw==", + "dev": true, + "requires": { + "anymatch": "2.0.0", + "async-each": "1.0.1", + "braces": "2.3.1", + "glob-parent": "3.1.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "4.0.0", + "normalize-path": "2.1.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0", + "upath": "1.0.4" + } + }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", @@ -9387,6 +10927,270 @@ "ms": "2.0.0" } }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "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-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.1", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.9", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + }, "yargs": { "version": "6.6.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", @@ -9420,12 +11224,20 @@ } }, "webpack-merge": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.1.1.tgz", - "integrity": "sha512-geQsZ86YkXOVOjvPC5yv3JSNnL6/X3Kzh935AQ/gJNEYXEfJDQFu/sdFuktS9OW2JcH/SJec8TGfRdrpHshH7A==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.1.2.tgz", + "integrity": "sha512-/0QYwW/H1N/CdXYA2PNPVbsxO3u2Fpz34vs72xm03SRfg6bMNGfMJIQEpQjKRvkG2JvT6oRJFpDtSrwbX8Jzvw==", "dev": true, "requires": { - "lodash": "4.17.4" + "lodash": "4.17.5" + }, + "dependencies": { + "lodash": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", + "dev": true + } } }, "webpack-sources": { @@ -9447,9 +11259,9 @@ } }, "webpack-subresource-integrity": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-1.0.3.tgz", - "integrity": "sha1-wGBtQAkLBwzeQovsjfNgMhbkcus=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-1.0.4.tgz", + "integrity": "sha1-j6yKfo61n8ahZ2ioXJ2U7n+dDts=", "dev": true, "requires": { "webpack-core": "0.6.9" @@ -9461,7 +11273,7 @@ "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", "dev": true, "requires": { - "http-parser-js": "0.4.9", + "http-parser-js": "0.4.11", "websocket-extensions": "0.1.3" } }, @@ -9477,12 +11289,6 @@ "integrity": "sha1-RztRfsFZ4rhQBUl6E5g/CVQS404=", "dev": true }, - "whet.extend": { - "version": "0.9.9", - "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", - "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=", - "dev": true - }, "which": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", @@ -9517,13 +11323,12 @@ "dev": true }, "worker-farm": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.5.2.tgz", - "integrity": "sha512-XxiQ9kZN5n6mmnW+mFJ+wXjNNI/Nx4DIdaAKLX1Bn6LYBWlN/zaBhu34DQYPZ1AJobQuu67S2OfDdNSVULvXkQ==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz", + "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==", "dev": true, "requires": { - "errno": "0.1.4", - "xtend": "4.0.1" + "errno": "0.1.7" } }, "wrap-ansi": { @@ -9541,21 +11346,16 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "ws": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.2.tgz", - "integrity": "sha1-iiRPoFJAHgjJiGz0SoUYnh/UBn8=", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", "dev": true, "requires": { - "options": "0.0.6", - "ultron": "1.0.2" + "async-limiter": "1.0.0", + "safe-buffer": "5.1.1", + "ultron": "1.1.1" } }, - "wtf-8": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wtf-8/-/wtf-8-1.0.0.tgz", - "integrity": "sha1-OS2LotDxw00e4tYw8V0O+2jhBIo=", - "dev": true - }, "xml-char-classes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/xml-char-classes/-/xml-char-classes-1.0.0.tgz", @@ -9569,35 +11369,45 @@ "dev": true, "requires": { "sax": "1.2.4", - "xmlbuilder": "9.0.4" + "xmlbuilder": "9.0.7" + }, + "dependencies": { + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + } } }, "xmlbuilder": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.4.tgz", - "integrity": "sha1-UZy0ymhtAFqEINNJbz8MruzKWA8=", + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", "dev": true }, - "xmlhttprequest": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", - "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" - }, "xmlhttprequest-ssl": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz", - "integrity": "sha1-GFqIjATspGw+QHDZn3tJ3jUomS0=", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", "dev": true }, + "xregexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", + "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", + "dev": true, + "optional": true + }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" }, "xxhashjs": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/xxhashjs/-/xxhashjs-0.2.1.tgz", - "integrity": "sha1-m76b6JYUKXbfo0wGGy0GjEPTDeA=", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/xxhashjs/-/xxhashjs-0.2.2.tgz", + "integrity": "sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==", "dev": true, "requires": { "cuint": "0.2.2" @@ -9668,9 +11478,9 @@ "dev": true }, "zone.js": { - "version": "0.8.18", - "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.8.18.tgz", - "integrity": "sha512-knKOBQM0oea3/x9pdyDuDi7RhxDlJhOIkeixXSiTKWLgs4LpK37iBc+1HaHwzlciHUKT172CymJFKo8Xgh+44Q==" + "version": "0.8.26", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.8.26.tgz", + "integrity": "sha512-W9Nj+UmBJG251wkCacIkETgra4QgBo/vgoEkb4a2uoLzpQG7qF9nzwoLXWU5xj3Fg2mxGvEDh47mg24vXccYjA==" } } } diff --git a/app/webFrontend/package.json b/app/webFrontend/package.json index d875fe0ac..5fc74bc1c 100644 --- a/app/webFrontend/package.json +++ b/app/webFrontend/package.json @@ -2,7 +2,7 @@ "name": "geli-web-frontend", "description": "This is the WebFronted-Package.json for geli.", "repository": "h-da/geli", - "version": "0.6.0", + "version": "0.7.0", "license": "GPL-3.0", "scripts": { "ng": "ng", @@ -12,62 +12,67 @@ "build": "ng build --prod --sourcemaps", "build-pr": "ng build --prod", "test": "ng test", + "test-ci": "ng test --single-run", "lint": "ng lint", + "lint:fix": "ng lint --fix", "e2e": "ng e2e" }, "private": true, "dependencies": { - "@angular/animations": "^5.1.0", - "@angular/cdk": "^5.0.0", - "@angular/common": "^5.1.0", - "@angular/compiler": "^5.1.0", - "@angular/core": "^5.1.0", - "@angular/forms": "^5.1.0", - "@angular/http": "^5.1.0", - "@angular/material": "^5.0.0", - "@angular/platform-browser": "^5.1.0", - "@angular/platform-browser-dynamic": "^5.1.0", - "@angular/router": "^5.1.0", + "@angular-devkit/core": "^0.4.9", + "@angular/animations": "^5.2.10", + "@angular/cdk": "^5.2.5", + "@angular/common": "^5.2.10", + "@angular/compiler": "^5.2.10", + "@angular/core": "^5.2.10", + "@angular/forms": "^5.2.10", + "@angular/http": "^5.2.10", + "@angular/material": "^5.2.5", + "@angular/platform-browser": "^5.2.10", + "@angular/platform-browser-dynamic": "^5.2.10", + "@angular/router": "^5.2.10", "@ngx-translate/core": "^9.1.1", "@ngx-translate/http-loader": "^2.0.1", - "@swimlane/ngx-charts": "^7.0.1", - "angular2-lightbox": "^1.2.1", + "@schematics/package-update": "^0.4.9", + "@swimlane/ngx-charts": "^7.2.0", + "angular2-lightbox": "^1.3.0", "blueimp-md5": "^2.10.0", - "core-js": "^2.5.2", - "d3": "^4.12.0", - "file-saver": "^1.3.3", + "core-js": "^2.5.5", + "d3": "^5.1.0", + "file-saver": "1.3.3", + "jasmine": "^3.1.0", "knuth-shuffle": "^1.0.8", - "markdown-it": "^8.4.0", + "markdown-it": "^8.4.1", "material-design-icons": "^3.0.1", - "moment": "^2.19.3", - "ng2-ace-editor": "^0.3.4", + "moment": "^2.22.0", + "ng2-ace-editor": "^0.3.7", "ng2-dragula": "^1.5.0", "ng2-file-upload": "^1.3.0", - "node-sass": "^4.7.2", - "raven-js": "^3.20.1", - "rxjs": "^5.5.5", - "zone.js": "^0.8.18" + "node-sass": "^4.9.0", + "raven-js": "^3.24.1", + "rxjs": "^5.5.10", + "zone.js": "^0.8.26" }, "devDependencies": { - "@angular-devkit/schematics": "0.0.40", - "@angular/cli": "1.6.0", - "@angular/compiler-cli": "^5.1.0", - "@schematics/angular": "^0.1.10", - "@types/jasmine": "2.8.2", + "@angular-devkit/schematics": "^0.4.9", + "@angular/cli": "1.7.3", + "@angular/compiler-cli": "^5.2.10", + "@types/file-saver": "^1.3.0", + "@types/jasmine": "2.8.6", "@types/jasminewd2": "^2.0.3", - "@types/node": "~8.0.57", - "codelyzer": "~4.0.1", - "jasmine-core": "~2.8.0", + "@types/node": "^8.10.10", + "codelyzer": "~4.2.1", + "jasmine-core": "~3.1.0", "jasmine-spec-reporter": "~4.2.1", - "karma": "~1.7.1", + "karma": "^2.0.2", "karma-chrome-launcher": "~2.2.0", "karma-cli": "~1.0.1", - "karma-coverage-istanbul-reporter": "^1.3.0", + "karma-coverage-istanbul-reporter": "^1.4.2", "karma-jasmine": "~1.1.1", - "karma-jasmine-html-reporter": "^0.2.2", - "protractor": "~5.2.1", - "ts-node": "~3.3.0", - "tslint": "~5.8.0", + "karma-jasmine-html-reporter": "^1.0.0", + "protractor": "^5.3.1", + "ts-node": "~5.0.1", + "tslint": "~5.9.1", "typescript": "2.4.2" } } diff --git a/app/webFrontend/src/app/about/general-info/contributor.model.ts b/app/webFrontend/src/app/about/general-info/contributor.model.ts index e16e76f82..3f655d13c 100644 --- a/app/webFrontend/src/app/about/general-info/contributor.model.ts +++ b/app/webFrontend/src/app/about/general-info/contributor.model.ts @@ -31,6 +31,16 @@ export class Contributor { return compare; } + // Check for position + compare = a.position.localeCompare(b.position); + if (compare !== 0) { + if (a.position === 'Lecturer') { + return -1; + } else { + return 1; + } + } + // Check for NAME compare = a.name.localeCompare(b.name); if (compare !== 0) { diff --git a/app/webFrontend/src/app/about/general-info/contributors.ts b/app/webFrontend/src/app/about/general-info/contributors.ts index 348edf729..35bc2ea26 100644 --- a/app/webFrontend/src/app/about/general-info/contributors.ts +++ b/app/webFrontend/src/app/about/general-info/contributors.ts @@ -8,22 +8,37 @@ export class ContributorsList { new Contributor('Thomas', 'Sauer', '16WiSe', 'Initiator', 'thomassss') , new Contributor('Ute', 'Trapp', '17SuSe', 'Lecturer', 'utetrapp') , new Contributor('David', 'Müller', '17SuSe', 'Lecturer', 'd89') + // Contributors + , new Contributor('Steffen', 'Großpersky', '17SuSe', 'Contributor', 'grosspersky') + , new Contributor('Alexander', 'Eimer', '17SuSe', 'Contributor', 'aeimer') + , new Contributor('Ken', 'Hasenbank', '17SuSe', 'Contributor', 'khase') + // Students - , new Contributor('Andreas', 'Schroll', '17WiSe', 'Student', 'AndreasSchroll') - , new Contributor('Sinisa', 'Jovanovic', '17WiSe', 'Student', 'jsinisa') + , new Contributor('Tobias', 'Neumann', '18SuSe', 'Student', 'Gargamil') + , new Contributor('Armel', 'Siewe', '18SuSe', 'Student', 'armel22') + , new Contributor('David', 'Boschmann', '18SuSe', 'Student', 'dboschm') + , new Contributor('Daniel', 'Kesselberg', '18SuSe', 'Student', 'danielkesselberg') + , new Contributor('Max', 'Leppla', '18SuSe', 'Student', 'mleppla') + , new Contributor('Michael', 'Narkus', '18SuSe', 'Student', 'MichaelNarkus') + , new Contributor('Torsten', 'Schlett', '18SuSe', 'Student', 'torss') + , new Contributor('Clara', 'Wurm', '18SuSe', 'Student', 'wurmc') + , new Contributor('Lukas', 'Schardt', '18SuSe', 'Student', 'lukas-schardt') + , new Contributor('Alper', 'Uygun', '18SuSe', 'Student', 'AlperUygun') + , new Contributor('Christoper', 'Nierobisch', '18SuSe', 'Student', 'ChrisEnpunkt') + , new Contributor('Florian', 'Witulski', '18SuSe', 'Student', 'fwitulski') + + , new Contributor('Andreas', 'Schroll', '17WiSe', 'Student', 'AndreasSchroll', '17WiSe') + , new Contributor('Sinisa', 'Jovanovic', '17WiSe', 'Student', 'jsinisa', '17WiSe') , new Contributor('Patrick', 'Skowronek', '17WiSe', 'Student', 'PatrickSkowronek') , new Contributor('Henrik', 'Ochs', '17WiSe', 'Student', 'HPunktOchs') - , new Contributor('Patrick', 'Schmelmer', '17WiSe', 'Student', 'shelmz') - , new Contributor('Michael', 'Pahlke', '17WiSe', 'Student', 'micpah') - , new Contributor('Felix', 'Brucker', '17SuSe', 'Student', 'felixbrucker', '17WiSe') - , new Contributor('Alexander', 'Eimer', '17SuSe', 'Student', 'aeimer', '17WiSe') - , new Contributor('Steffen', 'Großpersky', '17SuSe', 'Student', 'grosspersky', '17WiSe') - , new Contributor('Ken', 'Hasenbank', '17SuSe', 'Student', 'khase', '17WiSe') + + // Old Students + , new Contributor('Patrick', 'Schmelmer', '17WiSe', 'Student', 'shelmz', '17WiSe') + , new Contributor('Michael', 'Pahlke', '17WiSe', 'Student', 'micpah', '17WiSe') , new Contributor('Lukas', 'Korte', '17SuSe', 'Student', 'lukaskorte', '17WiSe') , new Contributor('Oliver', 'Neff', '17SuSe', 'Student', 'OliverNeff', '17WiSe') , new Contributor('Alexander', 'Weinfurter', '17SuSe', 'Student', 'alexweinfurter', '17WiSe') - // Old Students , new Contributor('Bernd', 'Noetscher', '17SuSe', 'Student', 'bernd-hda', '17SuSe') ]; } diff --git a/app/webFrontend/src/app/about/general-info/general-info.component.html b/app/webFrontend/src/app/about/general-info/general-info.component.html index d82d02652..eebe894c9 100644 --- a/app/webFrontend/src/app/about/general-info/general-info.component.html +++ b/app/webFrontend/src/app/about/general-info/general-info.component.html @@ -1,6 +1,6 @@

General Info

-

This app was initialized by Thomas Sauer +

This app was initialized by Thomas Sauer and brought to a production-ready state by students of the University of Applied Science in Darmstadt (h_da).

diff --git a/app/webFrontend/src/app/admin/admin-routing.module.ts b/app/webFrontend/src/app/admin/admin-routing.module.ts index 2142e6728..31737e5cf 100644 --- a/app/webFrontend/src/app/admin/admin-routing.module.ts +++ b/app/webFrontend/src/app/admin/admin-routing.module.ts @@ -2,8 +2,8 @@ import {NgModule} from '@angular/core'; import {RouterModule, Routes} from '@angular/router'; import {AuthGuardService} from '../shared/services/auth-guard.service'; import {UserAdminComponent} from './user-admin/user-admin.component'; -import {ImprintAdminComponent} from './imprint-admin/imprint-admin.component'; import {AdminComponent} from './admin.component'; +import {AdminMarkdownEditComponent} from '../shared/components/admin-markdown-edit/admin-markdown-edit.component'; const routes: Routes = [ { @@ -24,8 +24,8 @@ const routes: Routes = [ data: {roles: ['admin']} }, { - path: 'imprint', - component: ImprintAdminComponent, + path: 'markdownEdit', + component: AdminMarkdownEditComponent, canActivate: [AuthGuardService], data: {roles: ['admin']} }, diff --git a/app/webFrontend/src/app/admin/admin.component.html b/app/webFrontend/src/app/admin/admin.component.html index 6096118b5..5fb3c60e9 100644 --- a/app/webFrontend/src/app/admin/admin.component.html +++ b/app/webFrontend/src/app/admin/admin.component.html @@ -4,9 +4,12 @@

Administration

- +
diff --git a/app/webFrontend/src/app/admin/admin.module.ts b/app/webFrontend/src/app/admin/admin.module.ts index 94ead7323..96c641e7c 100644 --- a/app/webFrontend/src/app/admin/admin.module.ts +++ b/app/webFrontend/src/app/admin/admin.module.ts @@ -5,7 +5,6 @@ import {AdminComponent} from './admin.component'; import {FormsModule, ReactiveFormsModule} from '@angular/forms'; import {RouterModule} from '@angular/router'; import {SharedModule} from '../shared/shared.module'; -import {ImprintAdminComponent} from './imprint-admin/imprint-admin.component'; import {AceEditorModule} from 'ng2-ace-editor'; import {AdminRoutingModule} from './admin-routing.module'; @@ -22,7 +21,6 @@ import {AdminRoutingModule} from './admin-routing.module'; declarations: [ AdminComponent, UserAdminComponent, - ImprintAdminComponent ] }) export class AdminModule { diff --git a/app/webFrontend/src/app/admin/imprint-admin/imprint-admin.component.scss b/app/webFrontend/src/app/admin/imprint-admin/imprint-admin.component.scss deleted file mode 100644 index 8b1378917..000000000 --- a/app/webFrontend/src/app/admin/imprint-admin/imprint-admin.component.scss +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/webFrontend/src/app/admin/imprint-admin/imprint-admin.component.ts b/app/webFrontend/src/app/admin/imprint-admin/imprint-admin.component.ts deleted file mode 100644 index 6a299e31b..000000000 --- a/app/webFrontend/src/app/admin/imprint-admin/imprint-admin.component.ts +++ /dev/null @@ -1,48 +0,0 @@ -import {Component, OnInit} from '@angular/core'; -import {MarkdownService} from '../../shared/services/markdown.service'; -import {ConfigService} from '../../shared/services/data.service'; -import {IConfig} from '../../../../../../shared/models/IConfig'; -import {MatSnackBar} from '@angular/material'; -import 'brace'; -import 'brace/mode/markdown'; -import 'brace/theme/github'; -import {errorCodes} from '../../../../../../api/src/config/errorCodes'; - -@Component({ - selector: 'app-imprint-admin', - templateUrl: './imprint-admin.component.html', - styleUrls: ['./imprint-admin.component.scss'] -}) -export class ImprintAdminComponent implements OnInit { - imprint: IConfig; - text: string; - constructor(private service: ConfigService, - private mdService: MarkdownService, - private snackBar: MatSnackBar) { } - - ngOnInit() { - void this.loadImprint() - } - - async loadImprint() { - try { - this.imprint = await this.service.readSingleItem('imprint'); - this.text = this.imprint.value; - } catch (error) { - this.text = ''; - } - } - onSave(markdown: string ) { - try { - void this.service.updateItem({_id: 'imprint', data: markdown}); - this.snackBar.open('Imprint saved', '', {duration: 3000}) - } catch (error) { - this.snackBar.open(errorCodes.save.couldNotSaveImprint.text, '', {duration: 3000}) - } - void this.loadImprint(); - } - onCancel() { - void this.loadImprint(); - } - -} diff --git a/app/webFrontend/src/app/admin/user-admin/user-admin.component.html b/app/webFrontend/src/app/admin/user-admin/user-admin.component.html index e2cbc248b..d724e1b1e 100644 --- a/app/webFrontend/src/app/admin/user-admin/user-admin.component.html +++ b/app/webFrontend/src/app/admin/user-admin/user-admin.component.html @@ -13,7 +13,7 @@

Users

{{user.profile.firstName}} {{user.profile.lastName}} {{user.email}} - + {{role}} diff --git a/app/webFrontend/src/app/admin/user-admin/user-admin.component.ts b/app/webFrontend/src/app/admin/user-admin/user-admin.component.ts index db23c2188..0288079b3 100644 --- a/app/webFrontend/src/app/admin/user-admin/user-admin.component.ts +++ b/app/webFrontend/src/app/admin/user-admin/user-admin.component.ts @@ -5,6 +5,7 @@ import {ShowProgressService} from '../../shared/services/show-progress.service'; import {MatSnackBar} from '@angular/material'; import {IUser} from '../../../../../../shared/models/IUser'; import {DialogService} from '../../shared/services/dialog.service'; +import {UserService} from '../../shared/services/user.service'; @Component({ selector: 'app-user-admin', @@ -16,11 +17,12 @@ export class UserAdminComponent implements OnInit { allUsers: IUser[]; availableRoles: String[]; - constructor(private userService: UserDataService, + constructor(private userDataService: UserDataService, private router: Router, private showProgress: ShowProgressService, public snackBar: MatSnackBar, - public dialogService: DialogService) { + public dialogService: DialogService, + private userService: UserService) { } ngOnInit() { @@ -33,20 +35,20 @@ export class UserAdminComponent implements OnInit { } getUsers() { - this.userService.readItems().then(users => { + this.userDataService.readItems().then(users => { this.allUsers = users; }); } getRoles() { - this.userService.getRoles().then(roles => { + this.userDataService.getRoles().then(roles => { this.availableRoles = roles; }); } updateRole(userIndex: number) { this.showProgress.toggleLoadingGlobal(true); - this.userService.updateItem(this.allUsers[userIndex]).then( + this.userDataService.updateItem(this.allUsers[userIndex]).then( (val) => { this.showProgress.toggleLoadingGlobal(false); this.snackBar.open('Role of user ' + val.email + ' successfully updated to ' + val.role, '', {duration: 3000}); @@ -69,7 +71,7 @@ export class UserAdminComponent implements OnInit { .subscribe(res => { if (res) { this.showProgress.toggleLoadingGlobal(true); - this.userService.deleteItem(this.allUsers[userIndex]).then( + this.userDataService.deleteItem(this.allUsers[userIndex]).then( (val) => { this.showProgress.toggleLoadingGlobal(false); this.snackBar.open('User ' + val + ' was successfully deleted.', '', {duration: 3000}); diff --git a/app/webFrontend/src/app/app-routing.module.ts b/app/webFrontend/src/app/app-routing.module.ts index f2b07507e..34b6493a8 100644 --- a/app/webFrontend/src/app/app-routing.module.ts +++ b/app/webFrontend/src/app/app-routing.module.ts @@ -9,11 +9,15 @@ import {RouterModule, Routes} from '@angular/router'; import {ImprintComponent} from './imprint/imprint.component'; import {UserSettingsComponent} from './user/user-settings/user-settings.component'; import {AuthGuardService} from './shared/services/auth-guard.service'; +import {ActivationResendComponent} from './auth/activation-resend/activation-resend.component'; +import {NotfoundComponent} from './shared/components/notfound/notfound.component'; const routes: Routes = [ + {path: 'not-found', component: NotfoundComponent}, {path: '', component: StartComponent, pathMatch: 'full'}, {path: 'login', component: LoginComponent}, {path: 'register', component: RegisterComponent}, + {path: 'activation-resend', component: ActivationResendComponent}, {path: 'activate/:token', component: ActivationComponent}, {path: 'reset', component: ResetComponent}, {path: 'reset/:token', component: ResetComponent}, @@ -42,7 +46,8 @@ const routes: Routes = [ component: UserSettingsComponent, canActivate: [AuthGuardService], data: {roles: ['student']} - } + }, + {path: '**', redirectTo: 'not-found'} ]; @NgModule({ diff --git a/app/webFrontend/src/app/app.component.html b/app/webFrontend/src/app/app.component.html index 4d23dd484..0d279a5a7 100644 --- a/app/webFrontend/src/app/app.component.html +++ b/app/webFrontend/src/app/app.component.html @@ -17,13 +17,14 @@ - + - + + + + +

{{'auth.registration.resendActivationButton'|translate}}

+
+ +
+
+ + +
+ + {{'common.validation.required'|translate}} + + + common.validation.minLength + +
+
+
+ +
+ + +
+ + {{'common.validation.required'|translate}} + + {{uidError}} + + {{'common.validation.required'|translate}} + +
+
+
+ +
+ + +
+ + {{'common.validation.required'|translate}} + + {{mailError}} + + {{'common.validation.invalid'|translate}} + +
+
+
+ + +
{{formError}}
+ + +
+
+ +
+ +
+
diff --git a/app/webFrontend/src/app/auth/activation-resend/activation-resend.component.scss b/app/webFrontend/src/app/auth/activation-resend/activation-resend.component.scss new file mode 100644 index 000000000..6a2230741 --- /dev/null +++ b/app/webFrontend/src/app/auth/activation-resend/activation-resend.component.scss @@ -0,0 +1,25 @@ +:host { + flex-grow: 1; + display: flex; + justify-content: center; + align-items: center; +} + +.resendActivation-card { + width: 100%; + max-width: 400px; + + .mat-form-field, + .mat-radio-group { + width: 100%; + } + +} + +#resendActivationFormError{ + margin-bottom: 20px; +} + +.bottom-buttons{ + margin-top: 20px; +} diff --git a/app/webFrontend/src/app/auth/activation-resend/activation-resend.component.spec.ts b/app/webFrontend/src/app/auth/activation-resend/activation-resend.component.spec.ts new file mode 100644 index 000000000..4fe75361f --- /dev/null +++ b/app/webFrontend/src/app/auth/activation-resend/activation-resend.component.spec.ts @@ -0,0 +1,28 @@ +/* tslint:disable:no-unused-variable */ +import {async, ComponentFixture, TestBed} from '@angular/core/testing'; +import {By} from '@angular/platform-browser'; +import {DebugElement} from '@angular/core'; + +import {ActivationResendComponent} from './activation-resend.component'; + +describe('ActivationResendComponent', () => { + let component: ActivationResendComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ActivationResendComponent] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ActivationResendComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/webFrontend/src/app/auth/activation-resend/activation-resend.component.ts b/app/webFrontend/src/app/auth/activation-resend/activation-resend.component.ts new file mode 100644 index 000000000..78427208a --- /dev/null +++ b/app/webFrontend/src/app/auth/activation-resend/activation-resend.component.ts @@ -0,0 +1,122 @@ +import {Component, OnInit} from '@angular/core'; +import {Validators, FormGroup, FormBuilder, FormControl} from '@angular/forms'; +import {AuthenticationService} from '../../shared/services/authentication.service'; +import {Router} from '@angular/router'; +import {ShowProgressService} from '../../shared/services/show-progress.service'; +import {MatSnackBar} from '@angular/material'; +import {errorCodes} from '../../../../../../api/src/config/errorCodes'; +import {TitleService} from '../../shared/services/title.service'; +import {emailValidator} from '../../shared/validators/validators'; + +@Component({ + selector: 'app-activation-resend', + templateUrl: './activation-resend.component.html', + styleUrls: ['./activation-resend.component.scss'] +}) +export class ActivationResendComponent implements OnInit { + resendActivationForm: FormGroup; + resendActivationDone = false; + loading = false; + uidError = null; + mailError = null; + formError = null; + + private trimFormFields() { + + this.resendActivationForm.value.profile.lastName = this.resendActivationForm.value.profile.lastName.trim(); + this.resendActivationForm.value.uid = this.resendActivationForm.value.uid.trim(); + this.resendActivationForm.value.email = this.resendActivationForm.value.email.trim(); + + } + + constructor(private router: Router, + private authenticationService: AuthenticationService, + private showProgress: ShowProgressService, + private snackBar: MatSnackBar, + private formBuilder: FormBuilder, + private titleService: TitleService, ) { + } + + ngOnInit() { + this.titleService.setTitle('Resend Activation'); + // reset login status + this.authenticationService.unsetAuthData(); + this.generateForm(); + } + + clearAllErrors() { + this.mailError = null; + this.uidError = null; + this.formError = null; + } + + check() { + this.trimFormFields(); + } + + async resendActivation() { + this.clearAllErrors(); + this.loading = true; + this.showProgress.toggleLoadingGlobal(this.loading); + this.resendActivationForm.value.email = this.resendActivationForm.value.email.replace(/\s/g, '').toLowerCase(); + this.trimFormFields(); + try { + await this.authenticationService.resendActivation(this.resendActivationForm.value.profile.lastName, + this.resendActivationForm.value.uid, this.resendActivationForm.value.email); + this.resendActivationDone = true; + } catch (err) { + this.handleError(err); + } + this.loading = false; + this.showProgress.toggleLoadingGlobal(this.loading); + + } + + private handleError(err) { + switch (err.error.message) { + case errorCodes.mail.duplicate.code: { + this.mailError = errorCodes.mail.duplicate.text; + break; + } + case errorCodes.user.userNotFound.code: { + this.formError = errorCodes.user.userNotFound.text; + break; + } + case errorCodes.user.userAlreadyActive.code: { + this.formError = errorCodes.user.userAlreadyActive.text; + break; + } + case errorCodes.user.retryAfter.code: { + const timeTillNextTry = err.headers.get('retry-after'); + const timeTillNextTrySec = timeTillNextTry % 60; + const timeTillNextTryMin = (timeTillNextTry / 60); + this.formError = errorCodes.user.retryAfter.text + Math.floor(timeTillNextTryMin) + ' min ' + + Math.floor(timeTillNextTrySec) + ' sec.'; + break; + } + default: { + this.snackBar.open('Activation Resend failed', 'Dismiss'); + } + } + } + + generateForm() { + this.resendActivationForm = this.formBuilder.group({ + profile: this.formBuilder.group({ + lastName: ['', Validators.compose([Validators.required, Validators.minLength(2)])], + }), + uid: ['', Validators.compose([Validators.required, this.validateMatriculationNumber.bind(this)])], + email: ['', Validators.compose([Validators.required, emailValidator])] + }); + } + + + validateMatriculationNumber(control: FormControl) { + if ((control.value as String).length <= 0) { + return {uidValidator: true}; + } + return null; + } +} + + diff --git a/app/webFrontend/src/app/auth/auth.module.ts b/app/webFrontend/src/app/auth/auth.module.ts index 47b822f77..c64e6eed3 100644 --- a/app/webFrontend/src/app/auth/auth.module.ts +++ b/app/webFrontend/src/app/auth/auth.module.ts @@ -3,6 +3,7 @@ import {CommonModule} from '@angular/common'; import {LoginComponent} from './login/login.component'; import {RegisterComponent} from './register/register.component'; import {ActivationComponent} from './activation/activation.component'; +import {ActivationResendComponent} from './activation-resend/activation-resend.component'; import {ResetComponent} from './reset/reset.component'; import {FormsModule, ReactiveFormsModule} from '@angular/forms'; import {SharedModule} from '../shared/shared.module'; @@ -21,6 +22,7 @@ import {RouterModule} from '@angular/router'; RegisterComponent, ActivationComponent, ResetComponent, + ActivationResendComponent, ] }) export class AuthModule { diff --git a/app/webFrontend/src/app/auth/login/login.component.scss b/app/webFrontend/src/app/auth/login/login.component.scss index 3f8c86a47..babf53d64 100644 --- a/app/webFrontend/src/app/auth/login/login.component.scss +++ b/app/webFrontend/src/app/auth/login/login.component.scss @@ -13,3 +13,7 @@ width: 100%; } } + +.mat-raised-button { + margin-top: 7px; +} diff --git a/app/webFrontend/src/app/auth/login/login.component.ts b/app/webFrontend/src/app/auth/login/login.component.ts index 0c8343312..7c12ae78c 100644 --- a/app/webFrontend/src/app/auth/login/login.component.ts +++ b/app/webFrontend/src/app/auth/login/login.component.ts @@ -5,7 +5,7 @@ import {AuthenticationService} from '../../shared/services/authentication.servic import {AuthGuardService} from '../../shared/services/auth-guard.service'; import {FormBuilder, FormGroup, Validators} from '@angular/forms'; import {ShowProgressService} from '../../shared/services/show-progress.service'; -import {MatSnackBar} from '@angular/material'; +import {SnackBarService} from '../../shared/services/snack-bar.service'; import {TitleService} from '../../shared/services/title.service'; import {TranslateService} from '@ngx-translate/core'; @@ -23,7 +23,7 @@ export class LoginComponent implements OnInit { private authGuard: AuthGuardService, private authenticationService: AuthenticationService, private showProgress: ShowProgressService, - private snackBar: MatSnackBar, + private snackBar: SnackBarService, private formBuilder: FormBuilder, private titleService: TitleService, private translate: TranslateService) { @@ -47,7 +47,7 @@ export class LoginComponent implements OnInit { this.loading = false; this.translate.get(['auth.loginSuccess', 'common.dismiss']).subscribe((t: string) => { - this.snackBar.open(t['auth.loginSuccess'], t['common.dismiss'], {duration: 2000}); + this.snackBar.open(t['auth.loginSuccess']); }); }) .catch(error => { @@ -56,14 +56,9 @@ export class LoginComponent implements OnInit { this.translate.get([ 'auth.loginFailed', - 'common.dismiss', `auth.loginFailedError.${error.error.message}` ]).subscribe((t: string) => { - this.snackBar.open( - t['auth.loginFailed'] + ': ' + t[`auth.loginFailedError.${error.error.message}`], - t['common.dismiss'], - {duration: 2000} - ); + this.snackBar.open(t['auth.loginFailed'] + ': ' + t[`auth.loginFailedError.${error.error.message}`]); }); }); } diff --git a/app/webFrontend/src/app/auth/register/register.component.html b/app/webFrontend/src/app/auth/register/register.component.html index 425b57cd5..694973cdd 100644 --- a/app/webFrontend/src/app/auth/register/register.component.html +++ b/app/webFrontend/src/app/auth/register/register.component.html @@ -21,7 +21,7 @@
+ [placeholder]="'common.profile.firstName'|translate" maxlength="64"/>
@@ -31,11 +31,15 @@ class="text-danger" translate [translateParams]="{min:2}"> common.validation.minLength + + common.validation.maxLength +
+ [placeholder]="'common.profile.lastName'|translate" maxlength="64"/>
@@ -45,6 +49,10 @@ class="text-danger" translate [translateParams]="{min:2}"> common.validation.minLength + + common.validation.maxLength +
@@ -57,11 +65,11 @@ {{mailError}} {{'common.validation.instituteMail'|translate}} {{'common.validation.invalid'|translate}} @@ -86,13 +94,18 @@ [disabled]="loading || !registerForm?.valid">{{'common.register'|translate}} +
+ - + - + +
diff --git a/app/webFrontend/src/app/auth/register/register.component.scss b/app/webFrontend/src/app/auth/register/register.component.scss index 43b3a4dfb..d1115ce21 100644 --- a/app/webFrontend/src/app/auth/register/register.component.scss +++ b/app/webFrontend/src/app/auth/register/register.component.scss @@ -22,4 +22,8 @@ vertical-align: middle; } } + + .bottom-buttons{ + margin-top: 20px; + } } diff --git a/app/webFrontend/src/app/auth/register/register.component.ts b/app/webFrontend/src/app/auth/register/register.component.ts index 71b1300d9..efcf1c9db 100644 --- a/app/webFrontend/src/app/auth/register/register.component.ts +++ b/app/webFrontend/src/app/auth/register/register.component.ts @@ -3,10 +3,11 @@ import {Validators, FormGroup, FormBuilder, FormControl} from '@angular/forms'; import {AuthenticationService} from '../../shared/services/authentication.service'; import {Router} from '@angular/router'; import {ShowProgressService} from '../../shared/services/show-progress.service'; -import {MatSnackBar} from '@angular/material'; +import {SnackBarService} from '../../shared/services/snack-bar.service'; import {errorCodes} from '../../../../../../api/src/config/errorCodes'; import {TitleService} from '../../shared/services/title.service'; import {APIInfoService} from '../../shared/services/data.service'; +import {emailValidator} from '../../shared/validators/validators'; @Component({ selector: 'app-register', @@ -34,10 +35,10 @@ export class RegisterComponent implements OnInit { constructor(private router: Router, private authenticationService: AuthenticationService, private showProgress: ShowProgressService, - private snackBar: MatSnackBar, + private snackBar: SnackBarService, private formBuilder: FormBuilder, private titleService: TitleService, - private apiInfoService: APIInfoService, ) { + private apiInfoService: APIInfoService) { } ngOnInit() { @@ -76,42 +77,44 @@ export class RegisterComponent implements OnInit { (val) => { this.registrationDone = true; }) - .catch((error) => { - const errormessage = error.json().message || error.json().errmsg; - switch (errormessage) { - case errorCodes.mail.duplicate.code: { - this.mailError = errorCodes.mail.duplicate.text; - break; - } - case errorCodes.mail.noTeacher.code: { - this.mailError = errorCodes.mail.noTeacher.text; - break; - } - case errorCodes.duplicateUid.code: { - this.uidError = errorCodes.duplicateUid.text; - break; - } - default: { - this.snackBar.open('Registration failed', 'Dismiss'); - } - } + .catch((err) => { + this.handleError(err); }) .then(() => { this.loading = false; this.showProgress.toggleLoadingGlobal(this.loading); - }) - ; + }); + } + + private handleError(err) { + switch (err.error.message) { + case errorCodes.mail.duplicate.code: { + this.mailError = errorCodes.mail.duplicate.text; + break; + } + case errorCodes.mail.noTeacher.code: { + this.mailError = errorCodes.mail.noTeacher.text; + break; + } + case errorCodes.duplicateUid.code: { + this.uidError = errorCodes.duplicateUid.text; + break; + } + default: { + this.snackBar.open('Registration failed'); + } + } } generateForm() { this.registerForm = this.formBuilder.group({ profile: this.formBuilder.group({ - firstName: ['', Validators.compose([Validators.required, Validators.minLength(2)])], - lastName: ['', Validators.compose([Validators.required, Validators.minLength(2)])], + firstName: ['', Validators.compose([Validators.required, Validators.minLength(2), Validators.maxLength(64)])], + lastName: ['', Validators.compose([Validators.required, Validators.minLength(2), Validators.maxLength(64)])], }), - email: ['', Validators.compose([Validators.required, Validators.email, this.validateTeacherEmail.bind(this)])], + email: ['', Validators.compose([emailValidator, Validators.required, this.validateTeacherEmail.bind(this)])], uid: ['', [this.validateMatriculationNumber.bind(this)]] - }) + }); } validateTeacherEmail(control: FormControl) { diff --git a/app/webFrontend/src/app/auth/reset/reset.component.ts b/app/webFrontend/src/app/auth/reset/reset.component.ts index 4b9bb6c60..e66d97e2c 100644 --- a/app/webFrontend/src/app/auth/reset/reset.component.ts +++ b/app/webFrontend/src/app/auth/reset/reset.component.ts @@ -3,10 +3,11 @@ import {Component, OnInit} from '@angular/core'; import {AuthenticationService} from '../../shared/services/authentication.service'; import {FormBuilder, FormGroup, Validators} from '@angular/forms'; import {ShowProgressService} from '../../shared/services/show-progress.service'; -import {MatSnackBar} from '@angular/material'; +import {SnackBarService} from '../../shared/services/snack-bar.service'; import {ActivatedRoute, Router} from '@angular/router'; import {isNullOrUndefined} from 'util'; import {TitleService} from '../../shared/services/title.service'; +import {emailValidator} from '../../shared/validators/validators'; @Component({ templateUrl: './reset.component.html', @@ -24,7 +25,7 @@ export class ResetComponent implements OnInit { constructor(private router: Router, private authenticationService: AuthenticationService, private showProgress: ShowProgressService, - private snackBar: MatSnackBar, + private snackBar: SnackBarService, private formBuilder: FormBuilder, private route: ActivatedRoute, private titleService: TitleService) { @@ -43,14 +44,19 @@ export class ResetComponent implements OnInit { } requestReset() { + if (!this.resetForm.valid) { + this.snackBar.open('The email address you entered is not valid.'); + return; + } + this.showProgress.toggleLoadingGlobal(true); this.loading = true; this.authenticationService.requestReset(this.resetForm.value.email.replace(/\s/g, '').toLowerCase()) .then( (val) => { - this.snackBar.open('Check your mails', 'Dismiss'); + this.snackBar.open('Check your mails'); }, (error) => { - this.snackBar.open('Request failed', 'Dismiss'); + this.snackBar.open('Request failed'); }) .then(() => { this.showProgress.toggleLoadingGlobal(false); @@ -65,9 +71,9 @@ export class ResetComponent implements OnInit { .then( (val) => { this.router.navigate(['/login']); - this.snackBar.open('Your password has been reset', 'Dismiss'); + this.snackBar.open('Your password has been reset'); }, (error) => { - this.snackBar.open('Your password could not be reset', 'Dismiss'); + this.snackBar.open('Your password could not be reset'); }) .then(() => { this.showProgress.toggleLoadingGlobal(false); @@ -80,7 +86,7 @@ export class ResetComponent implements OnInit { this.resetForm = this.formBuilder.group({}); } else { this.resetForm = this.formBuilder.group({ - email: ['', Validators.required] + email: ['', emailValidator ] }); } } diff --git a/app/webFrontend/src/app/course/course-container/course-container.component.html b/app/webFrontend/src/app/course/course-container/course-container.component.html index ac8b84ba8..fc3eb6a21 100644 --- a/app/webFrontend/src/app/course/course-container/course-container.component.html +++ b/app/webFrontend/src/app/course/course-container/course-container.component.html @@ -3,7 +3,9 @@
diff --git a/app/webFrontend/src/app/course/course-container/course-container.component.scss b/app/webFrontend/src/app/course/course-container/course-container.component.scss index 1b3ad4e61..3a63134dd 100644 --- a/app/webFrontend/src/app/course/course-container/course-container.component.scss +++ b/app/webFrontend/src/app/course/course-container/course-container.component.scss @@ -27,6 +27,8 @@ .open-toggle { color: map-get($app-primary, 'default'); + width: 50px; + height: 50px; transition: transform 0.3s; float: right; transform: rotate(-90deg); @@ -34,3 +36,9 @@ transform: rotate(0); } } + +.arrow { + font-size: 36px; + height: 36px; + width: 36px; +} diff --git a/app/webFrontend/src/app/course/course-container/course-container.component.ts b/app/webFrontend/src/app/course/course-container/course-container.component.ts index cdeab0a40..0c32d2dd1 100644 --- a/app/webFrontend/src/app/course/course-container/course-container.component.ts +++ b/app/webFrontend/src/app/course/course-container/course-container.component.ts @@ -3,7 +3,7 @@ import {MatDialog, MatSnackBar} from '@angular/material'; import {UserService} from '../../shared/services/user.service'; import {CourseService, UserDataService} from '../../shared/services/data.service'; import {Router} from '@angular/router'; -import {ICourse} from '../../../../../../shared/models/ICourse'; +import {ICourseDashboard} from '../../../../../../shared/models/ICourseDashboard'; import {errorCodes} from '../../../../../../api/src/config/errorCodes'; import {LastVisitedCourseContainerUpdater} from '../../shared/utils/LastVisitedCourseContainerUpdater'; @@ -15,7 +15,7 @@ import {LastVisitedCourseContainerUpdater} from '../../shared/utils/LastVisitedC export class CourseContainerComponent implements OnInit { @Input() - courses: ICourse[]; + courses: ICourseDashboard[]; @Input() expand: boolean; @Input() @@ -69,12 +69,10 @@ export class CourseContainerComponent implements OnInit { }); } - leaveCallback({courseId}) { - this.courseService.leaveStudent(courseId).then((res) => { + leaveCallback(result) { + if (result) { // reload courses to update enrollment status this.onLeave.emit(); - }).catch((err) => { - this.snackBar.open(`${err.statusText}: ${JSON.parse(err._body).message}`, '', {duration: 5000}); - }); + } } } diff --git a/app/webFrontend/src/app/course/course-detail/course-detail.component.html b/app/webFrontend/src/app/course/course-detail/course-detail.component.html index 63343bbc7..1e4d3cddf 100644 --- a/app/webFrontend/src/app/course/course-detail/course-detail.component.html +++ b/app/webFrontend/src/app/course/course-detail/course-detail.component.html @@ -1,11 +1,34 @@
-

{{course?.name}}

+ + + +
+
+
+
+ {{course?.courseAdmin.profile.firstName + " " + course?.courseAdmin.profile.lastName}}
+ Admin +
+
+
+ +
+
+
+
+ {{teacher.profile.firstName + " " + teacher.profile.lastName}}
+ Teacher +
+
+
+

{{course?.description}}

- +
diff --git a/app/webFrontend/src/app/course/course-detail/course-detail.component.scss b/app/webFrontend/src/app/course/course-detail/course-detail.component.scss index 9115e0aae..12e200ca4 100644 --- a/app/webFrontend/src/app/course/course-detail/course-detail.component.scss +++ b/app/webFrontend/src/app/course/course-detail/course-detail.component.scss @@ -10,3 +10,45 @@ .course-header { display: block; } + +.mat-chip-list { + display: inline-block; + margin-left: 5px; +} + +.mat-chip { + position: relative; + cursor: pointer; + margin-top: 5px; + margin-bottom: 5px; + margin-right: 20px; +} + +.img-wrapper { + left: -10px; + width: 50px; + height: 50px; + position: absolute; + border-radius: 50%; + +} + +.teacher-name{ + margin-left: 35px; + text-align: center; +} + +.teacher-image { + background-size: cover; + vertical-align: middle; +} + +.admin-name{ + margin-left: 35px; + text-align: center; +} + +.admin-image { + background-size: cover; + vertical-align: middle; +} diff --git a/app/webFrontend/src/app/course/course-detail/course-detail.component.ts b/app/webFrontend/src/app/course/course-detail/course-detail.component.ts index 7e40b7347..858de7696 100644 --- a/app/webFrontend/src/app/course/course-detail/course-detail.component.ts +++ b/app/webFrontend/src/app/course/course-detail/course-detail.component.ts @@ -4,10 +4,14 @@ import 'rxjs/add/operator/switchMap'; import {CourseService, UserDataService} from '../../shared/services/data.service'; import {ICourse} from '../../../../../../shared/models/ICourse'; import {UserService} from '../../shared/services/user.service'; +import {IUser} from '../../../../../../shared/models/IUser'; +import {User} from '../../models/User'; import {MatSnackBar, MatDialog} from '@angular/material'; import {DownloadCourseDialogComponent} from './download-course-dialog/download-course-dialog.component'; import {TitleService} from '../../shared/services/title.service'; import {LastVisitedCourseContainerUpdater} from '../../shared/utils/LastVisitedCourseContainerUpdater'; +import {DialogService} from '../../shared/services/dialog.service'; + @Component({ selector: 'app-course-detail', @@ -17,7 +21,6 @@ import {LastVisitedCourseContainerUpdater} from '../../shared/utils/LastVisitedC export class CourseDetailComponent implements OnInit { course: ICourse; - id: string; constructor(private router: Router, @@ -27,7 +30,8 @@ export class CourseDetailComponent implements OnInit { private snackBar: MatSnackBar, private dialog: MatDialog, private titleService: TitleService, - private userDataService: UserDataService) { + private userDataService: UserDataService, + private dialogService: DialogService) { } ngOnInit() { @@ -38,18 +42,21 @@ export class CourseDetailComponent implements OnInit { this.titleService.setTitle('Course'); } - getCourse(courseId: string) { - this.courseService.readSingleItem(courseId).then( - (course: any) => { - this.course = course; - LastVisitedCourseContainerUpdater.addCourseToLastVisitedCourses(courseId, this.userService, this.userDataService); - this.titleService.setTitleCut(['Course: ', this.course.name]); - }, - (errorResponse: Response) => { - if (errorResponse.status === 401) { - this.snackBar.open('You are not authorized to view this course.', '', {duration: 3000}); - } - }); + async getCourse(courseId: string) { + try { + this.course = await this.courseService.readCourseToView(courseId); + this.titleService.setTitleCut(['Course: ', this.course.name]); + LastVisitedCourseContainerUpdater.addCourseToLastVisitedCourses(courseId, this.userService, this.userDataService); + } catch (errorResponse) { + if (errorResponse.status === 401) { + this.snackBar.open('You are not authorized to view this course.', '', {duration: 3000}); + } else if (errorResponse.status === 404) { + this.snackBar.open('Your selected course is not available.', '', {duration: 3000}); + this.router.navigate(['/not-found']); + } else { + this.snackBar.open('Something went wrong: ' + errorResponse.message, '', {duration: 3000}); + } + } } openDownloadDialog() { @@ -58,4 +65,9 @@ export class CourseDetailComponent implements OnInit { width: '800px' }); } + + showUserProfile(teacher: User) { + this.dialogService.userProfile(teacher); + } + } diff --git a/app/webFrontend/src/app/course/course-detail/download-course-dialog/download-course-dialog.component.html b/app/webFrontend/src/app/course/course-detail/download-course-dialog/download-course-dialog.component.html index 6e68421c1..11e3c8da8 100644 --- a/app/webFrontend/src/app/course/course-detail/download-course-dialog/download-course-dialog.component.html +++ b/app/webFrontend/src/app/course/course-detail/download-course-dialog/download-course-dialog.component.html @@ -1,6 +1,7 @@

{{course.name}}

-No lectures to download! -

Select units or files which you want to download

+No course material available for download +
+

Select units or files which you want to download in a zip

@@ -13,6 +14,7 @@

Select All

+
diff --git a/app/webFrontend/src/app/course/course-detail/download-course-dialog/download-course-dialog.component.ts b/app/webFrontend/src/app/course/course-detail/download-course-dialog/download-course-dialog.component.ts index d012ddb5b..5a6b8b128 100644 --- a/app/webFrontend/src/app/course/course-detail/download-course-dialog/download-course-dialog.component.ts +++ b/app/webFrontend/src/app/course/course-detail/download-course-dialog/download-course-dialog.component.ts @@ -7,7 +7,7 @@ import {IDownload} from '../../../../../../../shared/models/IDownload'; import {IDownloadSize} from '../../../../../../../shared/models/IDownloadSize'; import {SaveFileService} from '../../../shared/services/save-file.service'; -import { saveAs } from 'file-saver/FileSaver'; +import {saveAs} from 'file-saver/FileSaver'; @Component({ selector: 'app-download-course-dialog', @@ -37,15 +37,18 @@ export class DownloadCourseDialogComponent implements OnInit { this.disableDownloadButton = false; this.course = this.data.course; this.chkbox = false; + if (!this.checkForEmptyLectures()) { + this.disableDownloadButton = true; + } } onChange() { if (this.chkbox) { this.childLectures.forEach(lecture => { - if (lecture.chkbox === false) { - lecture.chkbox = true; - lecture.onChange(); - } + + lecture.chkbox = true; + lecture.onChange(); + }); } else { this.childLectures.forEach(lecture => lecture.chkbox = false); @@ -54,32 +57,52 @@ export class DownloadCourseDialogComponent implements OnInit { } onChildEvent() { - let childChecked = false; + const childChecked: boolean[] = new Array(); + this.childLectures.forEach(lec => { - if (lec.chkbox === true) { - childChecked = true; - this.chkbox = true; + if (lec.chkbox === true && !lec.childUnits.find(unit => unit.chkbox === false)) { + childChecked.push(true); + } else { + childChecked.push(false); } }); - if (!childChecked) { + + if (childChecked.find(bol => bol === false) !== undefined) { this.chkbox = false; + } else { + this.chkbox = true; } } calcSumFileSize(): number { let sum = 0; - this.childLectures.forEach(lecture => { - lecture.childUnits.forEach(unit => { - if (unit.files) { - unit.childUnits.forEach(fileUnit => { - if (fileUnit.chkbox) { - sum = sum + fileUnit.file.size; + this.childLectures.forEach(lecture => { + lecture.childUnits.forEach(unit => { + if (unit.files) { + unit.childUnits.forEach(fileUnit => { + if (fileUnit.chkbox) { + sum = sum + fileUnit.file.size; + } + }); } }); - } }); - }); - return sum; + return sum; + } + + checkForEmptyLectures(): boolean { + if (!this.course.lectures.length) { + return false; + } + + let foundUnits = false; + + for (const lec of this.course.lectures) { + if (lec.units.length) { + foundUnits = true; + } + } + return foundUnits; } async downloadAndClose() { @@ -87,6 +110,7 @@ export class DownloadCourseDialogComponent implements OnInit { const obj = await this.buildObject(); if (obj.lectures.length === 0) { this.snackBar.open('No units selected!', 'Dismiss', {duration: 3000}); + this.disableDownloadButton = false; return; } const downloadObj = obj; @@ -126,7 +150,7 @@ export class DownloadCourseDialogComponent implements OnInit { const files = []; unit.childUnits.forEach((file, index) => { if (file.chkbox && !file.showDL) { - files.push(index); + files.push(file.file._id); } }); units.push({unitId: unit.unit._id, files: files}); diff --git a/app/webFrontend/src/app/course/course-detail/download-course-dialog/downloadCheckBoxes/lecture-checkbox.component.html b/app/webFrontend/src/app/course/course-detail/download-course-dialog/downloadCheckBoxes/lecture-checkbox.component.html index ae8a550fe..b9d557f5b 100644 --- a/app/webFrontend/src/app/course/course-detail/download-course-dialog/downloadCheckBoxes/lecture-checkbox.component.html +++ b/app/webFrontend/src/app/course/course-detail/download-course-dialog/downloadCheckBoxes/lecture-checkbox.component.html @@ -1,12 +1,12 @@ +

{{lecture.name}}

Lecture - +
- - +
\ No newline at end of file diff --git a/app/webFrontend/src/app/course/course-detail/download-course-dialog/downloadCheckBoxes/lecture-checkbox.component.ts b/app/webFrontend/src/app/course/course-detail/download-course-dialog/downloadCheckBoxes/lecture-checkbox.component.ts index 3eebc622f..998513726 100644 --- a/app/webFrontend/src/app/course/course-detail/download-course-dialog/downloadCheckBoxes/lecture-checkbox.component.ts +++ b/app/webFrontend/src/app/course/course-detail/download-course-dialog/downloadCheckBoxes/lecture-checkbox.component.ts @@ -1,6 +1,6 @@ import { Component, OnInit, ViewEncapsulation, Input, ViewChildren, QueryList, Output, - EventEmitter + EventEmitter, AfterViewChecked, ChangeDetectorRef } from '@angular/core'; import {ILecture} from '../../../../../../../../shared/models/ILecture'; import {UnitCheckboxComponent} from './unit-checkbox.component'; @@ -11,7 +11,7 @@ import {UnitCheckboxComponent} from './unit-checkbox.component'; styleUrls: ['./lecture-checkbox.component.scss'], encapsulation: ViewEncapsulation.None }) -export class LectureCheckboxComponent implements OnInit { +export class LectureCheckboxComponent implements OnInit, AfterViewChecked { @Input() chkbox: boolean; @Input() @@ -20,14 +20,25 @@ export class LectureCheckboxComponent implements OnInit { childUnits: QueryList; @Output() valueChanged: EventEmitter = new EventEmitter(); + showCheckBox = true; - constructor() { + constructor(private changeDetector: ChangeDetectorRef) { this.chkbox = false; } ngOnInit() { } + ngAfterViewChecked() { + this.showCheckBox = this.childUnits.toArray().some((unit: UnitCheckboxComponent) => { + return unit.showCheckBox === true; + }); + // force angular to detect the change otherwise an error(ExpressionChangedAfterItHasBeenCheckedError) is threw. + // see: https://github.com/angular/angular/issues/17572 + this.changeDetector.detectChanges(); + } + + onChange() { if (this.chkbox) { this.childUnits.forEach(unit => { diff --git a/app/webFrontend/src/app/course/course-detail/download-course-dialog/downloadCheckBoxes/unit-checkbox.component.html b/app/webFrontend/src/app/course/course-detail/download-course-dialog/downloadCheckBoxes/unit-checkbox.component.html index d9d191178..a0152e73e 100644 --- a/app/webFrontend/src/app/course/course-detail/download-course-dialog/downloadCheckBoxes/unit-checkbox.component.html +++ b/app/webFrontend/src/app/course/course-detail/download-course-dialog/downloadCheckBoxes/unit-checkbox.component.html @@ -2,7 +2,7 @@

{{unit.name}}

{{unitDesc}} - + diff --git a/app/webFrontend/src/app/course/course-detail/download-course-dialog/downloadCheckBoxes/unit-checkbox.component.ts b/app/webFrontend/src/app/course/course-detail/download-course-dialog/downloadCheckBoxes/unit-checkbox.component.ts index 1349c0f11..3f1717dc7 100644 --- a/app/webFrontend/src/app/course/course-detail/download-course-dialog/downloadCheckBoxes/unit-checkbox.component.ts +++ b/app/webFrontend/src/app/course/course-detail/download-course-dialog/downloadCheckBoxes/unit-checkbox.component.ts @@ -4,8 +4,9 @@ import { } from '@angular/core'; import {IUnit} from '../../../../../../../../shared/models/units/IUnit'; import {IFileUnit} from '../../../../../../../../shared/models/units/IFileUnit'; -import {IVideoUnit} from '../../../../../../../../shared/models/units/IVideoUnit'; import {UploadUnitCheckboxComponent} from './upload-unit-checkbox.component'; +import {MatSnackBar} from '@angular/material'; +import {ConfigService} from '../../../../shared/services/data.service'; @Component({ @@ -29,9 +30,9 @@ export class UnitCheckboxComponent implements OnInit { files; childUnitDesc: string; + showCheckBox = true; // false if the unit has only large files - constructor() { - + constructor(public snackBar: MatSnackBar, private configService: ConfigService) { } ngOnInit() { @@ -41,6 +42,7 @@ export class UnitCheckboxComponent implements OnInit { this.files = fileUnit.files; this.unitDesc = 'File Unit'; this.childUnitDesc = 'File'; + this.hasOnlyLargeFiles().then((result: boolean) => this.showCheckBox = !result); break; case 'task': this.unitDesc = 'Task Unit'; @@ -96,4 +98,18 @@ export class UnitCheckboxComponent implements OnInit { } this.valueChanged.emit(); } + + async hasOnlyLargeFiles() { + const _downloadMaxFileSize = this.configService.downloadMaxFileSize; + const downloadMaxFileSize = _downloadMaxFileSize ? _downloadMaxFileSize : await this.configService.getDownloadMaxFileSize(); + + if (!this.files) { + return false; + } else { + return this.files.every(file => { + return file.size / 1024 > downloadMaxFileSize; + }); + } + } + } diff --git a/app/webFrontend/src/app/course/course-detail/download-course-dialog/downloadCheckBoxes/upload-unit-checkbox.component.ts b/app/webFrontend/src/app/course/course-detail/download-course-dialog/downloadCheckBoxes/upload-unit-checkbox.component.ts index bf1ce2865..9fb263cc1 100644 --- a/app/webFrontend/src/app/course/course-detail/download-course-dialog/downloadCheckBoxes/upload-unit-checkbox.component.ts +++ b/app/webFrontend/src/app/course/course-detail/download-course-dialog/downloadCheckBoxes/upload-unit-checkbox.component.ts @@ -1,6 +1,8 @@ import {Component, Input, Output, OnInit, EventEmitter} from '@angular/core'; import {IFile} from '../../../../../../../../shared/models/mediaManager/IFile'; import {BackendService} from '../../../../shared/services/backend.service'; +import {ConfigService} from '../../../../shared/services/data.service'; + @Component({ selector: 'app-upload-unit-checkbox', @@ -19,13 +21,11 @@ export class UploadUnitCheckboxComponent implements OnInit { @Output() valueChanged: EventEmitter = new EventEmitter(); - constructor() { + constructor(private configService: ConfigService) { } ngOnInit() { - if (this.file.size / 1024 > 51200) { - this.showDL = true; - } + this.showDownloadButton().then((result: boolean) => this.showDL = result); } emitEvent() { @@ -36,7 +36,7 @@ export class UploadUnitCheckboxComponent implements OnInit { } downloadFile() { - const downloadLink = BackendService.API_URL + 'uploads/' + this.file.name; + const downloadLink = BackendService.API_URL + 'uploads/' + this.file.link; if (window.navigator && window.navigator.msSaveOrOpenBlob) { window.navigator.msSaveOrOpenBlob(downloadLink, this.file.name); @@ -50,7 +50,11 @@ export class UploadUnitCheckboxComponent implements OnInit { a.dispatchEvent(e); } } - + async showDownloadButton () { + const _downloadMaxFileSize = this.configService.downloadMaxFileSize; + const downloadMaxFileSize = _downloadMaxFileSize ? _downloadMaxFileSize : await this.configService.getDownloadMaxFileSize(); + return (this.file.size / 1024 > downloadMaxFileSize); + } } diff --git a/app/webFrontend/src/app/course/course-edit/course-manage-content/course-manage-content.component.ts b/app/webFrontend/src/app/course/course-edit/course-manage-content/course-manage-content.component.ts index fd6a1e9ae..af748e2fb 100644 --- a/app/webFrontend/src/app/course/course-edit/course-manage-content/course-manage-content.component.ts +++ b/app/webFrontend/src/app/course/course-edit/course-manage-content/course-manage-content.component.ts @@ -106,9 +106,9 @@ export class CourseManageContentComponent implements OnInit, OnDestroy { this.route.parent.parent.params.subscribe(params => { const courseId = params['id']; - this.courseService.readSingleItem(courseId).then( - (val: any) => { - this.course = val; + this.courseService.readCourseToEdit(courseId).then( + (course: ICourse) => { + this.course = course; this.dataSharingService.setDataForKey('course', this.course); this.setOpenedLectureAndUnit(); this.setAddLectureIfPresent(); @@ -221,7 +221,7 @@ export class CourseManageContentComponent implements OnInit, OnDestroy { async reloadCourse() { try { - this.course = (await this.courseService.readSingleItem(this.course._id)); + this.course = await this.courseService.readCourseToEdit(this.course._id); this.dataSharingService.setDataForKey('course', this.course); } catch (err) { this.snackBar.open('Couldn\'t reload Course', '', {duration: 3000}); @@ -244,7 +244,7 @@ export class CourseManageContentComponent implements OnInit, OnDestroy { this.snackBar.open(res.error.message, '', {duration: 3000}); } }); - }; + } onAddLecture() { this.onCloseAllForms.next(); @@ -269,7 +269,7 @@ export class CourseManageContentComponent implements OnInit, OnDestroy { path += `lecture/${lectureId}/unit/add/${type}`; this.router.navigate([path], {relativeTo: this.route}); }); - }; + } onImportUnit = () => { const openLectureId = this.dataSharingService.getDataForKey('openLectureId'); @@ -288,19 +288,19 @@ export class CourseManageContentComponent implements OnInit, OnDestroy { this.snackBar.open(res.error.message, '', {duration: 3000}); } }); - }; + } closeFab = () => { this.fabOpen = false; - }; + } onFabClick = () => { this.fabOpen = !this.fabOpen; - }; + } closeAddLecture = () => { this.dataSharingService.setDataForKey('lecture-create-mode', false); - }; + } private closeAllForms() { this.closeFab(); diff --git a/app/webFrontend/src/app/course/course-edit/course-manage-content/lecture-edit/lecture-edit.component.ts b/app/webFrontend/src/app/course/course-edit/course-manage-content/lecture-edit/lecture-edit.component.ts index 01d32c5d3..94bd0d4b5 100644 --- a/app/webFrontend/src/app/course/course-edit/course-manage-content/lecture-edit/lecture-edit.component.ts +++ b/app/webFrontend/src/app/course/course-edit/course-manage-content/lecture-edit/lecture-edit.component.ts @@ -85,7 +85,7 @@ export class LectureEditComponent implements OnInit, OnDestroy { this.saveFileService.save(lecture.name, JSON.stringify(lectureJSON, null, 2)); } catch (err) { - this.snackBar.open('Export lecture failed ' + err.json().message, 'Dismiss'); + this.snackBar.open('Export lecture failed ' + err.error.message, 'Dismiss'); } } @@ -173,18 +173,18 @@ export class LectureEditComponent implements OnInit, OnDestroy { closeEditLecture = () => { this.dataSharingService.setDataForKey('lecture-edit-mode', false); - }; + } onAddUnitDone = async () => { await this.reloadCourse(); this.closeAddUnit(); - }; + } closeAddUnit = () => { this.unsetAddUnit(); this.navigateToThisLecture(); - }; + } unsetAddUnit() { this.dataSharingService.setDataForKey('unit-create-mode', false); @@ -201,7 +201,7 @@ export class LectureEditComponent implements OnInit, OnDestroy { this.dataSharingService.setDataForKey('unit-edit-mode', true); this.dataSharingService.setDataForKey('unit-edit-element', unit); this.navigateToUnitEdit(unit._id); - }; + } isUnitCurrentlyOpen(unit: IUnit) { const isInEditMode = this.dataSharingService.getDataForKey('unit-edit-mode'); @@ -215,19 +215,19 @@ export class LectureEditComponent implements OnInit, OnDestroy { this.saveFileService.save(unit.name, JSON.stringify(unitJSON, null, 2)); } catch (err) { - this.snackBar.open('Export unit failed ' + err.json().message, 'Dismiss'); + this.snackBar.open('Export unit failed ' + err.error.message, 'Dismiss'); } - }; + } onEditUnitDone = async () => { await this.reloadCourse(); this.closeEditUnit(); - }; + } closeEditUnit = () => { this.unsetUnitEdit(); this.navigateToThisLecture(); - }; + } unsetUnitEdit() { this.dataSharingService.setDataForKey('unit-edit-mode', false); diff --git a/app/webFrontend/src/app/course/course-edit/course-media/course-media.component.ts b/app/webFrontend/src/app/course/course-edit/course-media/course-media.component.ts index f189e3f9b..d73075e8d 100644 --- a/app/webFrontend/src/app/course/course-edit/course-media/course-media.component.ts +++ b/app/webFrontend/src/app/course/course-edit/course-media/course-media.component.ts @@ -1,6 +1,7 @@ import {Component, OnInit} from '@angular/core'; import {ICourse} from '../../../../../../../shared/models/ICourse'; -import {MatDialog, MatSnackBar} from '@angular/material'; +import {MatDialog} from '@angular/material'; +import {SnackBarService} from '../../../shared/services/snack-bar.service'; import {CourseService, MediaService} from '../../../shared/services/data.service'; import {ActivatedRoute} from '@angular/router'; import {IDirectory} from '../../../../../../../shared/models/mediaManager/IDirectory'; @@ -26,16 +27,16 @@ export class CourseMediaComponent implements OnInit { public dialogService: DialogService, private courseService: CourseService, private route: ActivatedRoute, - private snackBar: MatSnackBar) { + private snackBar: SnackBarService) { } async ngOnInit() { this.folderBarVisible = false; - this.route.parent.params.subscribe( - async (params) => { + this.route.parent.params.subscribe(async (params) => { + try { // retrieve course - this.course = await this.courseService.readSingleItem(params['id']); + this.course = await this.courseService.readCourseToEdit(params['id']); // Check if course has root dir if (this.course.media === undefined) { @@ -44,15 +45,14 @@ export class CourseMediaComponent implements OnInit { // Update course await this.courseService.updateItem(this.course); // Reload course - this.course = await this.courseService.readSingleItem(this.course._id); + this.course = await this.courseService.readCourseToEdit(this.course._id); } await this.changeDirectory(this.course.media._id, true); - }, - error => { - this.snackBar.open('Could not load course', '', {duration: 3000}) + } catch (err) { + this.snackBar.open(err.error.message); } - ); + }); } async reloadDirectory() { @@ -121,27 +121,39 @@ export class CourseMediaComponent implements OnInit { } } + /** + * Remove selected files when user confirms + * @returns {Promise} + */ async removeSelectedFile() { this.toggleBlocked = true; - const res = await this.dialogService + + const deleteSelectedFiles = await this.dialogService .confirmRemove('selected files', '', 'course') .toPromise(); - this.toggleBlocked = false; - if (res) { - let failed = false; - this.selectedFiles.forEach(async file => { - await this.mediaService.deleteFile(file) - .catch(reason => { - this.snackBar.open('Could not remove file: ' + file.name, '', {duration: 2000}); - failed = true; - }); - }); - if (!failed) { - this.snackBar.open('Removed all selected files', '', {duration: 3000}); + + if (deleteSelectedFiles === false) { + return; + } + + const filesFailed = []; + for (const file of this.selectedFiles) { + try { + await this.mediaService.deleteFile(file); + } catch (err) { + filesFailed.push(file.name); } - this.selectedFiles = []; - await this.reloadDirectory(); } + + if (filesFailed.length === 0) { + this.snackBar.open('Removed all selected files'); + } else { + this.snackBar.openLong('Could not remove: ' + filesFailed.join(', ')); + } + + this.selectedFiles = []; + await this.reloadDirectory(); + this.toggleBlocked = false; } initFileDownload(file: IFile) { @@ -163,8 +175,8 @@ export class CourseMediaComponent implements OnInit { // Update file attributes file.name = value; await this.mediaService.updateFile(file) - .then(value2 => this.snackBar.open('Renamed file', '', {duration: 2000})) - .catch(reason => this.snackBar.open('Rename failed, Server error', '', {duration: 2000})); + .then(value2 => this.snackBar.open('Renamed file')) + .catch(reason => this.snackBar.open('Rename failed, Server error')); await this.reloadDirectory(); } }); diff --git a/app/webFrontend/src/app/course/course-edit/course-user-list/course-user-list-overview/course-user-list-overview.component.html b/app/webFrontend/src/app/course/course-edit/course-user-list/course-user-list-overview/course-user-list-overview.component.html index 871959e50..6ad388b77 100644 --- a/app/webFrontend/src/app/course/course-edit/course-user-list/course-user-list-overview/course-user-list-overview.component.html +++ b/app/webFrontend/src/app/course/course-edit/course-user-list/course-user-list-overview/course-user-list-overview.component.html @@ -34,10 +34,7 @@
- + @@ -23,18 +23,24 @@ -
+ - - - - diff --git a/app/webFrontend/src/app/course/course.component.ts b/app/webFrontend/src/app/course/course.component.ts index 935f6461f..813e7686a 100644 --- a/app/webFrontend/src/app/course/course.component.ts +++ b/app/webFrontend/src/app/course/course.component.ts @@ -1,9 +1,10 @@ import {Component, EventEmitter, Input, Output} from '@angular/core'; import 'rxjs/add/operator/switchMap'; import {UserService} from '../shared/services/user.service'; -import {ICourse} from '../../../../../shared/models/ICourse'; +import {ICourseDashboard, ENROLL_TYPE_ACCESSKEY} from '../../../../../shared/models/ICourseDashboard'; import {Router} from '@angular/router'; -import {MatDialog, MatSnackBar} from '@angular/material'; +import {MatDialog} from '@angular/material'; +import {SnackBarService} from '../shared/services/snack-bar.service'; import {AccessKeyDialog} from '../shared/components/access-key-dialog/access-key-dialog.component'; import {CourseService} from '../shared/services/data.service'; import {DialogService} from '../shared/services/dialog.service'; @@ -17,7 +18,7 @@ import {ShowProgressService} from '../shared/services/show-progress.service'; export class CourseComponent { @Input() - course: ICourse; + course: ICourseDashboard; @Output() onEnroll = new EventEmitter(); @@ -27,7 +28,7 @@ export class CourseComponent { constructor(public userService: UserService, private router: Router, private dialog: MatDialog, - private snackBar: MatSnackBar, + private snackBar: SnackBarService, private dialogService: DialogService, private showProgress: ShowProgressService, private courseService: CourseService) { @@ -44,7 +45,7 @@ export class CourseComponent { } enroll() { - if (this.course.hasAccessKey) { + if (this.course.enrollType === ENROLL_TYPE_ACCESSKEY) { // open dialog for accesskey const dialogRef = this.dialog.open(AccessKeyDialog); dialogRef.afterClosed().subscribe(result => { @@ -57,30 +58,27 @@ export class CourseComponent { } } + /** + * Leave course when user confirms + */ leave() { this.dialogService .confirm('Leave course ?', 'Do you really want to leave the course?', 'Leave') - .subscribe(res => { - if (res) { - this.showProgress.toggleLoadingGlobal(true); - this.courseService.leaveStudent(this.course._id) - .then(() => { - this.onLeave.emit({'courseId': this.course._id}); - this.snackBar.open('Left course successfully', '', {duration: 3000}); - }) - .catch((error) => { - this.snackBar.open(error, '', {duration: 3000}); - }) - .then(() => { - this.showProgress.toggleLoadingGlobal(false); - }); + .subscribe(async (leaveCourse) => { + if (leaveCourse === false) { + return; } - }); - } - isMemberOfCourse(course: ICourse) { - const user = this.userService.user; - return this.userService.isStudent() && - course.students.filter(obj => obj._id === user._id).length > 0; + this.showProgress.toggleLoadingGlobal(true); + + try { + await this.courseService.leaveStudent(this.course._id); + this.onLeave.emit({'courseId': this.course._id}); + } catch (err) { + this.snackBar.open(err.error.message); + } + + this.showProgress.toggleLoadingGlobal(false); + }); } } diff --git a/app/webFrontend/src/app/course/course.module.ts b/app/webFrontend/src/app/course/course.module.ts index 0732e013b..cdc79a3a0 100644 --- a/app/webFrontend/src/app/course/course.module.ts +++ b/app/webFrontend/src/app/course/course.module.ts @@ -14,9 +14,10 @@ import {LectureCheckboxComponent} from './course-detail/download-course-dialog/d import {UnitCheckboxComponent} from './course-detail/download-course-dialog/downloadCheckBoxes/unit-checkbox.component'; import {UploadUnitCheckboxComponent} from './course-detail/download-course-dialog/downloadCheckBoxes/upload-unit-checkbox.component'; import {DuplicationService, ExportService, ImportService} from '../shared/services/data.service'; +import {DialogService} from '../shared/services/dialog.service'; import {SaveFileService} from '../shared/services/save-file.service'; import {ReportModule} from '../report/report.module'; -import {RouterOutlet} from '@angular/router'; + @NgModule({ imports: [ @@ -47,6 +48,7 @@ import {RouterOutlet} from '@angular/router'; ExportService, DuplicationService, SaveFileService, + DialogService ], exports: [ CourseComponent, diff --git a/app/webFrontend/src/app/imprint/imprint.component.html b/app/webFrontend/src/app/imprint/imprint.component.html index bb231e3a1..4768ee3d3 100644 --- a/app/webFrontend/src/app/imprint/imprint.component.html +++ b/app/webFrontend/src/app/imprint/imprint.component.html @@ -1,2 +1,2 @@ -
+
diff --git a/app/webFrontend/src/app/imprint/imprint.component.ts b/app/webFrontend/src/app/imprint/imprint.component.ts index 925ee05b2..725473d31 100644 --- a/app/webFrontend/src/app/imprint/imprint.component.ts +++ b/app/webFrontend/src/app/imprint/imprint.component.ts @@ -1,7 +1,5 @@ import {Component, OnInit, ViewChild} from '@angular/core'; -import {IConfig} from '../../../../../shared/models/IConfig'; -import {MarkdownService} from '../shared/services/markdown.service'; -import {ConfigService} from '../shared/services/data.service'; +import {ImprintAndInfoService} from '../shared/services/imprint-and-info.service'; import {TitleService} from '../shared/services/title.service'; @Component({ @@ -10,25 +8,16 @@ import {TitleService} from '../shared/services/title.service'; styleUrls: ['./imprint.component.scss'] }) export class ImprintComponent implements OnInit { - imprint: IConfig; - imprintRendered: string; - constructor(private service: ConfigService, - private mdService: MarkdownService, + renderedContent: string; + constructor(private imprintService: ImprintAndInfoService, private titleService: TitleService) { } ngOnInit() { this.titleService.setTitle('Imprint'); - void this.loadImprint(); + this.getData(); } - async loadImprint() { - try { - this.imprint = await this.service.readSingleItem('public/imprint'); - this.renderHtml(); - } catch (error) { - this.imprintRendered = ''; - } - } - renderHtml() { - this.imprintRendered = this.mdService.render(this.imprint.value) || 'No imprint yet!'; + + async getData() { + this.renderedContent = await this.imprintService.loadConfig('imprint'); } } diff --git a/app/webFrontend/src/app/models/User.ts b/app/webFrontend/src/app/models/User.ts index 31bc3978e..713216756 100644 --- a/app/webFrontend/src/app/models/User.ts +++ b/app/webFrontend/src/app/models/User.ts @@ -1,36 +1,40 @@ import {IUser} from '../../../../../shared/models/IUser'; -import md5 from 'blueimp-md5'; -import {IFile} from '../../../../../shared/models/mediaManager/IFile'; +import {IFile} from '../../../../../shared/models/IFile'; + +const md5 = require('blueimp-md5'); export class User implements IUser { - _id: any; - uid: any; - email: string; - password: string; - profile: { firstName: string; lastName: string; picture: IFile; theme: string }; - role: string; - progress: any; - lastVisitedCourses: Array; + _id: any; + uid: any; + email: string; + password: string; + profile: { firstName: string; lastName: string; picture: IFile; theme: string }; + role: string; + progress: any; + lastVisitedCourses: Array; - constructor(user: IUser) { - this._id = user._id; - this.uid = user.uid; - this.email = user.email; - this.profile = user.profile; - this.role = user.role; - this.progress = user.progress; - this.lastVisitedCourses = user.lastVisitedCourses; - } + constructor(user: any) { + this._id = user._id; + this.uid = user.uid; + this.email = user.email; + this.profile = user.profile; + this.role = user.role; + this.progress = user.progress; + this.lastVisitedCourses = user.lastVisitedCourses; + } - getGravatarURL(size: number = 80) { - return `https://www.gravatar.com/avatar/${md5(this.email.toLowerCase())}.jpg?s=${size}&d=retro`; - } + getGravatarURL(size: number = 80) { + // Gravatar wants us to hash the email (for site to site consistency), + // - see https://en.gravatar.com/site/implement/hash/ - + // but we don't do that (anymore) for the sake of security & privacy. + return `https://www.gravatar.com/avatar/${md5(this._id)}.jpg?s=${size}&d=retro`; + } - getUserImageURL(size: number = 80) { - if (this.profile && this.profile.picture) { - return 'api/uploads/users/' + this.profile.picture.name; - } else { - return this.getGravatarURL(size); + getUserImageURL(size: number = 80) { + if (this.profile && this.profile.picture) { + return 'api/uploads/users/' + this.profile.picture.name; + } else { + return this.getGravatarURL(size); + } } - } } diff --git a/app/webFrontend/src/app/models/progress/CodeKataUnitProgress.ts b/app/webFrontend/src/app/models/progress/CodeKataUnitProgress.ts index 6e069ae1c..974d6d85a 100644 --- a/app/webFrontend/src/app/models/progress/CodeKataUnitProgress.ts +++ b/app/webFrontend/src/app/models/progress/CodeKataUnitProgress.ts @@ -15,7 +15,6 @@ export class CodeKataUnitProgress implements ICodeKataUnitProgress { this.unit = unit; this.course = this.unit._course; this.code = ''; - this.type = 'codeKata'; - this.type = 'codeKata'; + this.__t = 'codeKata'; } } diff --git a/app/webFrontend/src/app/models/progress/TaskUnitProgress.ts b/app/webFrontend/src/app/models/progress/TaskUnitProgress.ts index dd79b9863..014d55b97 100644 --- a/app/webFrontend/src/app/models/progress/TaskUnitProgress.ts +++ b/app/webFrontend/src/app/models/progress/TaskUnitProgress.ts @@ -15,7 +15,6 @@ export class TaskUnitProgress implements ITaskUnitProgress { this.unit = unit; this.course = unit._course; this.answers = {}; - this.type = 'task-unit-progress'; this.__t = 'task-unit-progress'; } } diff --git a/app/webFrontend/src/app/models/units/CodeKataUnit.ts b/app/webFrontend/src/app/models/units/CodeKataUnit.ts index aad406cb5..e6bd6bd5c 100644 --- a/app/webFrontend/src/app/models/units/CodeKataUnit.ts +++ b/app/webFrontend/src/app/models/units/CodeKataUnit.ts @@ -12,11 +12,13 @@ export class CodeKataUnit implements ICodeKataUnit { weight: number; updatedAt: string; createdAt: string; + visible: boolean; definition: string; code: string; test: string; deadline: string; + unitCreator: any; constructor(_course: ICourse) { this._course = _course; @@ -24,4 +26,5 @@ export class CodeKataUnit implements ICodeKataUnit { this.weight = 0; this.__t = 'code-kata'; } + } diff --git a/app/webFrontend/src/app/models/units/FileUnit.ts b/app/webFrontend/src/app/models/units/FileUnit.ts index a814984a0..658972d17 100644 --- a/app/webFrontend/src/app/models/units/FileUnit.ts +++ b/app/webFrontend/src/app/models/units/FileUnit.ts @@ -13,6 +13,8 @@ export class FileUnit implements IFileUnit { weight: number; updatedAt: string; createdAt: string; + visible: boolean; + unitCreator: any; files: IFile[] = []; fileUnitType: string; @@ -24,4 +26,5 @@ export class FileUnit implements IFileUnit { this.progressable = false; this.weight = 0; } + } diff --git a/app/webFrontend/src/app/models/units/FreeTextUnit.ts b/app/webFrontend/src/app/models/units/FreeTextUnit.ts index 2f8bed88a..0aeb784e3 100644 --- a/app/webFrontend/src/app/models/units/FreeTextUnit.ts +++ b/app/webFrontend/src/app/models/units/FreeTextUnit.ts @@ -12,6 +12,8 @@ export class FreeTextUnit implements IFreeTextUnit { __t: string; progressable: boolean; weight: number; + visible: boolean; + unitCreator: any; markdown: string; diff --git a/app/webFrontend/src/app/models/units/TaskUnit.ts b/app/webFrontend/src/app/models/units/TaskUnit.ts index 60ef85cca..0c4dfb97e 100644 --- a/app/webFrontend/src/app/models/units/TaskUnit.ts +++ b/app/webFrontend/src/app/models/units/TaskUnit.ts @@ -14,6 +14,8 @@ export class TaskUnit implements ITaskUnit { __t: string; progressable: boolean; weight: number; + visible: boolean; + unitCreator: any; tasks: ITask[] = []; deadline: string; diff --git a/app/webFrontend/src/app/notification/notification.component.ts b/app/webFrontend/src/app/notification/notification.component.ts index 4b54e0818..f2fde062b 100644 --- a/app/webFrontend/src/app/notification/notification.component.ts +++ b/app/webFrontend/src/app/notification/notification.component.ts @@ -95,4 +95,4 @@ function compareIds(a: any, b: any) { return -1; } return 0; -}; +} diff --git a/app/webFrontend/src/app/report/teacher-report/teacher-report.component.ts b/app/webFrontend/src/app/report/teacher-report/teacher-report.component.ts index e3ad8677f..78c9907ce 100644 --- a/app/webFrontend/src/app/report/teacher-report/teacher-report.component.ts +++ b/app/webFrontend/src/app/report/teacher-report/teacher-report.component.ts @@ -42,6 +42,6 @@ export class TeacherReportComponent implements OnInit { }) .catch((err) => { this.showProgress.toggleLoadingGlobal(false); - }) + }); } } diff --git a/app/webFrontend/src/app/admin/imprint-admin/imprint-admin.component.html b/app/webFrontend/src/app/shared/components/admin-markdown-edit/admin-markdown-edit.component.html similarity index 79% rename from app/webFrontend/src/app/admin/imprint-admin/imprint-admin.component.html rename to app/webFrontend/src/app/shared/components/admin-markdown-edit/admin-markdown-edit.component.html index 0bbfef877..7b4e17137 100644 --- a/app/webFrontend/src/app/admin/imprint-admin/imprint-admin.component.html +++ b/app/webFrontend/src/app/shared/components/admin-markdown-edit/admin-markdown-edit.component.html @@ -1,3 +1,2 @@ -

Imprint

- +

{{this.headingType}}

diff --git a/app/webFrontend/src/app/shared/components/admin-markdown-edit/admin-markdown-edit.component.scss b/app/webFrontend/src/app/shared/components/admin-markdown-edit/admin-markdown-edit.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/app/webFrontend/src/app/shared/components/admin-markdown-edit/admin-markdown-edit.component.spec.ts b/app/webFrontend/src/app/shared/components/admin-markdown-edit/admin-markdown-edit.component.spec.ts new file mode 100644 index 000000000..99d708c4d --- /dev/null +++ b/app/webFrontend/src/app/shared/components/admin-markdown-edit/admin-markdown-edit.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AdminMarkdownEditComponent } from './admin-markdown-edit.component'; + +describe('AdminMarkdownEditComponent', () => { + let component: AdminMarkdownEditComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ AdminMarkdownEditComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AdminMarkdownEditComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/webFrontend/src/app/shared/components/admin-markdown-edit/admin-markdown-edit.component.ts b/app/webFrontend/src/app/shared/components/admin-markdown-edit/admin-markdown-edit.component.ts new file mode 100644 index 000000000..435af207b --- /dev/null +++ b/app/webFrontend/src/app/shared/components/admin-markdown-edit/admin-markdown-edit.component.ts @@ -0,0 +1,55 @@ +import {Component, Input, OnInit} from '@angular/core'; +import {IConfig} from '../../../../../../../shared/models/IConfig'; +import {ConfigService} from '../../services/data.service'; +import {MarkdownService} from '../../services/markdown.service'; +import {errorCodes} from '../../../../../../../api/src/config/errorCodes'; +import {MatSnackBar} from '@angular/material'; +import {ActivatedRoute} from '@angular/router'; + +@Component({ + selector: 'app-admin-markdown-edit', + templateUrl: './admin-markdown-edit.component.html', + styleUrls: ['./admin-markdown-edit.component.scss'] +}) +export class AdminMarkdownEditComponent implements OnInit { + + config: IConfig; + text: string; + @Input() type: string; + @Input() headingType: string; + + constructor(private service: ConfigService, + private mdService: MarkdownService, + private snackBar: MatSnackBar, + private route: ActivatedRoute) { } + + ngOnInit() { + this.route.queryParams.subscribe(params => { + this.headingType = params['header']; + this.type = params['type']; + void this.loadConfig(); + }); + } + + async loadConfig() { + try { + this.config = await this.service.readSingleItem(this.type); + this.text = this.config.value; + } catch (error) { + this.text = ''; + } + } + onSave(markdown: string ) { + try { + void this.service.updateItem({_id: this.type, data: markdown}); + this.snackBar.open( this.headingType + ' saved', '', {duration: 3000}); + } catch (error) { + this.snackBar.open(errorCodes.save.couldNotSaveImprint.text, '', {duration: 3000}); + } + void this.loadConfig(); + } + onCancel() { + void this.loadConfig(); + } + +} diff --git a/app/webFrontend/src/app/shared/components/change-password-dialog/change-password-dialog.component.html b/app/webFrontend/src/app/shared/components/change-password-dialog/change-password-dialog.component.html index 6c651327b..c5e7a2673 100644 --- a/app/webFrontend/src/app/shared/components/change-password-dialog/change-password-dialog.component.html +++ b/app/webFrontend/src/app/shared/components/change-password-dialog/change-password-dialog.component.html @@ -1,12 +1,12 @@

Change Password

-
+ - +
diff --git a/app/webFrontend/src/app/shared/components/change-password-dialog/change-password-dialog.component.ts b/app/webFrontend/src/app/shared/components/change-password-dialog/change-password-dialog.component.ts index ad1be03a4..43cb65f49 100644 --- a/app/webFrontend/src/app/shared/components/change-password-dialog/change-password-dialog.component.ts +++ b/app/webFrontend/src/app/shared/components/change-password-dialog/change-password-dialog.component.ts @@ -1,6 +1,7 @@ import {Component, Input, OnInit} from '@angular/core'; import {IUser} from '../../../../../../../shared/models/IUser'; -import {MatDialogRef, MatSnackBar} from '@angular/material'; +import {MatDialogRef} from '@angular/material'; +import {SnackBarService} from '../../services/snack-bar.service'; import {FormGroup, FormBuilder} from '@angular/forms'; import {UserDataService} from '../../services/data.service'; import {UserService} from '../../services/user.service'; @@ -18,7 +19,7 @@ export class ChangePasswordDialogComponent implements OnInit { private formBuilder: FormBuilder, private userService: UserService, private userDataService: UserDataService, - public snackBar: MatSnackBar) { + public snackBar: SnackBarService) { this.generateForm(); } @@ -34,7 +35,7 @@ export class ChangePasswordDialogComponent implements OnInit { isSameUser() { if (this.user) { - return this.userService.user._id === this.user._id + return this.userService.user._id === this.user._id; } return false; } @@ -64,15 +65,14 @@ export class ChangePasswordDialogComponent implements OnInit { this.user = await this.prepUser(); try { const user = await this.userDataService.updateItem(this.user); - this.snackBar.open('Password successfully updated.', '', {duration: 3000}); + this.snackBar.open('Password successfully updated.'); this.dialogRef.close(); } catch (error) { - // console.dir(error); let errormsg = error.error.message; if (!errormsg || 0 === errormsg.length) { errormsg = 'Woops! Sth. went wrong. Please provide the correct Data and try again in a few Minutes!'; } - this.snackBar.open(errormsg, 'Dismiss'); + this.snackBar.open(errormsg); } } } diff --git a/app/webFrontend/src/app/shared/components/expandable-div/expandable-div.component.html b/app/webFrontend/src/app/shared/components/expandable-div/expandable-div.component.html index 882271a60..31244cbc3 100644 --- a/app/webFrontend/src/app/shared/components/expandable-div/expandable-div.component.html +++ b/app/webFrontend/src/app/shared/components/expandable-div/expandable-div.component.html @@ -1,7 +1,9 @@ {{title}} - diff --git a/app/webFrontend/src/app/shared/components/expandable-div/expandable-div.component.scss b/app/webFrontend/src/app/shared/components/expandable-div/expandable-div.component.scss index 0f47ef9c9..9ec3027f8 100644 --- a/app/webFrontend/src/app/shared/components/expandable-div/expandable-div.component.scss +++ b/app/webFrontend/src/app/shared/components/expandable-div/expandable-div.component.scss @@ -1,8 +1,10 @@ @import "../../../../variables"; -.toggle { +.open-toggle { display: inline-block; vertical-align: middle; + width: 50px; + height: 50px; color: map-get($app-primary,'default'); transition: transform 0.3s; transform: rotate(-90deg); @@ -18,3 +20,9 @@ .bold { font-weight: bold; } + +.arrow { + font-size: 36px; + height: 36px; + width: 36px; +} diff --git a/app/webFrontend/src/app/shared/components/filepicker-dialog/filepicker-dialog.component.ts b/app/webFrontend/src/app/shared/components/filepicker-dialog/filepicker-dialog.component.ts index 67109571a..32243b8b2 100644 --- a/app/webFrontend/src/app/shared/components/filepicker-dialog/filepicker-dialog.component.ts +++ b/app/webFrontend/src/app/shared/components/filepicker-dialog/filepicker-dialog.component.ts @@ -32,7 +32,7 @@ export class FilepickerDialog { }; this.uploader.onErrorItem = (item: FileItem, response: string, status: number, headers: ParsedResponseHeaders) => { return this.dialogRef.close({success: false, result: JSON.parse(response)}); - } + }; } public upload() { diff --git a/app/webFrontend/src/app/shared/components/notfound/notfound.component.html b/app/webFrontend/src/app/shared/components/notfound/notfound.component.html new file mode 100644 index 000000000..9d0ac828a --- /dev/null +++ b/app/webFrontend/src/app/shared/components/notfound/notfound.component.html @@ -0,0 +1,8 @@ +
+

Page not found :(

+

Maybe the page you are looking for has been removed, or you typed in the wrong URL

+ +
\ No newline at end of file diff --git a/app/webFrontend/src/app/shared/components/notfound/notfound.component.scss b/app/webFrontend/src/app/shared/components/notfound/notfound.component.scss new file mode 100644 index 000000000..c5a9ec944 --- /dev/null +++ b/app/webFrontend/src/app/shared/components/notfound/notfound.component.scss @@ -0,0 +1,9 @@ +.not-found-wrapper { + align-items: center; + display: flex; + flex-direction: column; + + .mat-button { + margin-top: 3em; + } +} \ No newline at end of file diff --git a/app/webFrontend/src/app/admin/imprint-admin/imprint-admin.component.spec.ts b/app/webFrontend/src/app/shared/components/notfound/notfound.component.spec.ts similarity index 53% rename from app/webFrontend/src/app/admin/imprint-admin/imprint-admin.component.spec.ts rename to app/webFrontend/src/app/shared/components/notfound/notfound.component.spec.ts index 5c4ae2641..052a1f6dc 100644 --- a/app/webFrontend/src/app/admin/imprint-admin/imprint-admin.component.spec.ts +++ b/app/webFrontend/src/app/shared/components/notfound/notfound.component.spec.ts @@ -1,20 +1,20 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { ImprintAdminComponent } from './imprint-admin.component'; +import { NotfoundComponent } from './notfound.component'; -describe('ImprintAdminComponent', () => { - let component: ImprintAdminComponent; - let fixture: ComponentFixture; +describe('NotfoundComponent', () => { + let component: NotfoundComponent; + let fixture: ComponentFixture; beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [ ImprintAdminComponent ] + declarations: [ NotfoundComponent ] }) .compileComponents(); })); beforeEach(() => { - fixture = TestBed.createComponent(ImprintAdminComponent); + fixture = TestBed.createComponent(NotfoundComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/app/webFrontend/src/app/shared/components/notfound/notfound.component.ts b/app/webFrontend/src/app/shared/components/notfound/notfound.component.ts new file mode 100644 index 000000000..6bcb3b2be --- /dev/null +++ b/app/webFrontend/src/app/shared/components/notfound/notfound.component.ts @@ -0,0 +1,19 @@ +import { Component, OnInit } from '@angular/core'; +import {Router} from '@angular/router'; + +@Component({ + selector: 'app-notfound', + templateUrl: './notfound.component.html', + styleUrls: ['./notfound.component.scss'] +}) +export class NotfoundComponent implements OnInit { + + constructor(private router: Router) { } + + ngOnInit() { + } + + public goBack() { + this.router.navigate(['/']); + } +} diff --git a/app/webFrontend/src/app/shared/components/password-input/password-input.component.ts b/app/webFrontend/src/app/shared/components/password-input/password-input.component.ts index 1f4b7e6ac..aa94c4e13 100644 --- a/app/webFrontend/src/app/shared/components/password-input/password-input.component.ts +++ b/app/webFrontend/src/app/shared/components/password-input/password-input.component.ts @@ -18,6 +18,6 @@ export class PasswordInputComponent implements OnInit { this.form.addControl('password', new FormControl('', Validators.compose( [Validators.required, Validators.pattern(errorCodes.password.regex.regex)]))); this.form.addControl('confirmPassword', new FormControl('', Validators.required)); - this.form.setValidators(matchPasswords('password', 'confirmPassword')) + this.form.setValidators(matchPasswords('password', 'confirmPassword')); } } diff --git a/app/webFrontend/src/app/shared/components/rename-dialog/rename-dialog.component.ts b/app/webFrontend/src/app/shared/components/rename-dialog/rename-dialog.component.ts index f7625195d..db1b4d84f 100644 --- a/app/webFrontend/src/app/shared/components/rename-dialog/rename-dialog.component.ts +++ b/app/webFrontend/src/app/shared/components/rename-dialog/rename-dialog.component.ts @@ -1,5 +1,6 @@ import {Component, Inject, Input, OnInit} from '@angular/core'; -import {MAT_DIALOG_DATA, MatDialogRef, MatSnackBar} from '@angular/material'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material'; +import {SnackBarService} from '../../services/snack-bar.service'; import {UploadDialog} from '../upload-dialog/upload-dialog.component'; @Component({ @@ -11,7 +12,7 @@ export class RenameDialogComponent implements OnInit { @Input() nameField = ''; constructor(public dialogRef: MatDialogRef, - private snackBar: MatSnackBar, + private snackBar: SnackBarService, @Inject(MAT_DIALOG_DATA) public data: any) { } ngOnInit() { @@ -24,7 +25,7 @@ export class RenameDialogComponent implements OnInit { // Check if Input is valid this.nameField = this.nameField.trim(); if (this.nameField.length === 0) { - this.snackBar.open('Input can\'t be empty', '', {duration: 2000}); + this.snackBar.open('Input can\'t be empty'); return; } diff --git a/app/webFrontend/src/app/shared/components/upload-dialog/upload-dialog.component.html b/app/webFrontend/src/app/shared/components/upload-dialog/upload-dialog.component.html index 9143901e1..62e84df8d 100644 --- a/app/webFrontend/src/app/shared/components/upload-dialog/upload-dialog.component.html +++ b/app/webFrontend/src/app/shared/components/upload-dialog/upload-dialog.component.html @@ -1,12 +1,21 @@
- - - - +
diff --git a/app/webFrontend/src/app/shared/components/upload-dialog/upload-dialog.component.scss b/app/webFrontend/src/app/shared/components/upload-dialog/upload-dialog.component.scss index de66dfc43..8b44222f4 100644 --- a/app/webFrontend/src/app/shared/components/upload-dialog/upload-dialog.component.scss +++ b/app/webFrontend/src/app/shared/components/upload-dialog/upload-dialog.component.scss @@ -1,3 +1,5 @@ +@import "../../../../variables"; +@import "../../../../styles/file-list"; .tab-content { margin-top: 1rem; @@ -13,3 +15,22 @@ .preview img, .camera video { width: 320px; } + +.file-dropzone { + display: table; + height: 7.5rem; + width: 100%; + cursor: pointer; + + border: dotted 2px map-get($app-primary, 'default'); + + &.nv-file-over { + border-color: map-get($app-accent, 'default'); + } + + span { + display: table-cell; + vertical-align: middle; + text-align: center; + } +} diff --git a/app/webFrontend/src/app/shared/components/upload-dialog/upload-dialog.component.ts b/app/webFrontend/src/app/shared/components/upload-dialog/upload-dialog.component.ts index f6996ed84..a72964ac1 100644 --- a/app/webFrontend/src/app/shared/components/upload-dialog/upload-dialog.component.ts +++ b/app/webFrontend/src/app/shared/components/upload-dialog/upload-dialog.component.ts @@ -3,6 +3,7 @@ import {FileItem, FileUploader} from 'ng2-file-upload'; import {IUser} from '../../../../../../../shared/models/IUser'; import {MatDialogRef, MatSnackBar} from '@angular/material'; + @Component({ selector: 'app-upload-dialog', templateUrl: './upload-dialog.component.html', @@ -30,7 +31,8 @@ export class UploadDialog implements OnInit { headers: [{ name: 'Authorization', value: localStorage.getItem('token') - }] + }], + allowedFileType: ['image'], }); this.uploader.onCompleteItem = (item: any, response: any, status: any, headers: any) => { @@ -38,6 +40,7 @@ export class UploadDialog implements OnInit { return this.dialogRef.close({success: true, user: JSON.parse(response)}); }; + } changedTab($event: any) { @@ -48,6 +51,7 @@ export class UploadDialog implements OnInit { } } + private startWebcam() { const nativeVideo = this.webcam.nativeElement; if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { @@ -86,12 +90,6 @@ export class UploadDialog implements OnInit { this.pictureTaken = true; } - public uploadImage() { - this.dialogRef.disableClose = true; - this.showProgressBar = true; - this.uploader.uploadAll(); - } - public addImage() { this.dialogRef.disableClose = true; this.showProgressBar = true; @@ -121,4 +119,14 @@ export class UploadDialog implements OnInit { this.dialogRef.close(false); } + public startUpload() { + try { + this.uploader.uploadAll(); + } catch (error) { + this.snackBar.open('An error occured during the Upload', '', { duration: 3000 }); + } + + } + + } diff --git a/app/webFrontend/src/app/shared/components/upload-form/upload-form.component.ts b/app/webFrontend/src/app/shared/components/upload-form/upload-form.component.ts index 18bc1fca7..d1f404bd8 100644 --- a/app/webFrontend/src/app/shared/components/upload-form/upload-form.component.ts +++ b/app/webFrontend/src/app/shared/components/upload-form/upload-form.component.ts @@ -58,8 +58,14 @@ export class UploadFormComponent implements OnInit, OnChanges { this.fileUploader = new FileUploader(uploadOptions); + this.fileUploader.onCancelItem = (file) => { + // set error true, so dialog is not closed automatically + this.error = true; + this.snackBar.open(`upload cancelled for ${file._file.name}`, 'Dismiss'); + }; + this.fileUploader.onBuildItemForm = (fileItem: any, form: any) => { - form.append('data', JSON.stringify(this.additionalData)) + form.append('data', JSON.stringify(this.additionalData)); }; this.fileUploader.onBeforeUploadItem = (fileItem) => { @@ -80,16 +86,21 @@ export class UploadFormComponent implements OnInit, OnChanges { }; this.fileUploader.onCompleteItem = (file, response, status, headers) => { - const responseObject = JSON.parse(response); - if (status === 200) { - this.error = false; - } - if (responseObject._id && status === 200) { - if (this.first) { - this.first = false; + try { + const responseObject = JSON.parse(response); + + if (status === 200) { + this.error = false; + } + if (responseObject._id && status === 200) { + if (this.first) { + this.first = false; + } + // all subsequent (if any) uploads will be added to this unit + this.onFileUploaded.emit(responseObject); } - // all subsequent (if any) uploads will be added to this unit - this.onFileUploaded.emit(responseObject); + } catch (e) { + } }; @@ -116,7 +127,7 @@ export class UploadFormComponent implements OnInit, OnChanges { clearQueue() { this.fileUploader.clearQueue(); if (this.fileUploader.queue.length > 0) { - this.snackBar.open('Queue couldn\'t be cleared.', 'Dismiss') + this.snackBar.open('Queue couldn\'t be cleared.', 'Dismiss'); } else { this.onFileSelectedChange.emit(false); } diff --git a/app/webFrontend/src/app/shared/components/user-profile-dialog/user-profile-dialog.component.html b/app/webFrontend/src/app/shared/components/user-profile-dialog/user-profile-dialog.component.html new file mode 100644 index 000000000..993699bff --- /dev/null +++ b/app/webFrontend/src/app/shared/components/user-profile-dialog/user-profile-dialog.component.html @@ -0,0 +1,15 @@ + diff --git a/app/webFrontend/src/app/shared/components/user-profile-dialog/user-profile-dialog.component.scss b/app/webFrontend/src/app/shared/components/user-profile-dialog/user-profile-dialog.component.scss new file mode 100644 index 000000000..13f9a8b02 --- /dev/null +++ b/app/webFrontend/src/app/shared/components/user-profile-dialog/user-profile-dialog.component.scss @@ -0,0 +1,24 @@ +.user-profile-dialog-wrapper{ + text-align: center; +} + +.profile { + + .user-icon { + display: block; + width: 7rem; + height: 7rem; + background-size: cover; + margin: auto; + } + + .name { + margin-top: 1rem; + margin-bottom: 1.5rem; + } + + .user-data { + text-align: left; + margin-bottom: 1.5rem; + } +} diff --git a/app/webFrontend/src/app/shared/components/user-profile-dialog/user-profile-dialog.component.spec.ts b/app/webFrontend/src/app/shared/components/user-profile-dialog/user-profile-dialog.component.spec.ts new file mode 100644 index 000000000..3e18253de --- /dev/null +++ b/app/webFrontend/src/app/shared/components/user-profile-dialog/user-profile-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import {async, ComponentFixture, TestBed} from '@angular/core/testing'; + +import {UserProfileDialog} from './user-profile-dialog.component'; + +describe('UserProfileDialog', () => { + let component: UserProfileDialog; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [UserProfileDialog] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(UserProfileDialog); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/webFrontend/src/app/shared/components/user-profile-dialog/user-profile-dialog.component.ts b/app/webFrontend/src/app/shared/components/user-profile-dialog/user-profile-dialog.component.ts new file mode 100644 index 000000000..68dba308a --- /dev/null +++ b/app/webFrontend/src/app/shared/components/user-profile-dialog/user-profile-dialog.component.ts @@ -0,0 +1,22 @@ +import {Component, Input} from '@angular/core'; +import {MatDialogRef} from '@angular/material'; +import {User} from '../../../models/User'; +import {UserService} from '../../services/user.service'; + +@Component({ + selector: 'app-user-profile-dialog', + templateUrl: './user-profile-dialog.component.html', + styleUrls: ['./user-profile-dialog.component.scss'] +}) +export class UserProfileDialog { + + @Input() user: User; + + constructor(public dialogRef: MatDialogRef, + public userService: UserService) { + } + + canSeeUid() { + return (this.userService.isAdmin() || this.userService.isTeacher()) && this.user.uid; + } +} diff --git a/app/webFrontend/src/app/shared/directives/focus.directive.ts b/app/webFrontend/src/app/shared/directives/focus.directive.ts index 4e5d9a875..1ca4c9883 100644 --- a/app/webFrontend/src/app/shared/directives/focus.directive.ts +++ b/app/webFrontend/src/app/shared/directives/focus.directive.ts @@ -5,7 +5,7 @@ import { Directive, OnInit, ElementRef } from '@angular/core'; }) export class FocusDirective implements OnInit { - constructor(private elementRef: ElementRef) { }; + constructor(private elementRef: ElementRef) { } ngOnInit(): void { // set directly so the changeDetector knows it's set to true later diff --git a/app/webFrontend/src/app/shared/directives/user-image.directive.ts b/app/webFrontend/src/app/shared/directives/user-image.directive.ts index 493aa30c5..19e8e8284 100644 --- a/app/webFrontend/src/app/shared/directives/user-image.directive.ts +++ b/app/webFrontend/src/app/shared/directives/user-image.directive.ts @@ -1,4 +1,4 @@ -import {Directive, HostBinding, Input, OnInit} from '@angular/core'; +import {Directive, HostBinding, Input, OnInit, SimpleChange} from '@angular/core'; import {User} from '../../models/User'; import {IUser} from '../../../../../../shared/models/IUser'; @@ -23,12 +23,28 @@ export class UserImageDirective implements OnInit { constructor() { } + ngOnChanges(changes: { [propKey: string]: SimpleChange }) { + for (const propName in changes) { + if (changes.hasOwnProperty(propName)) { + const changedProp = changes[propName]; + this[propName] = changedProp.currentValue; + } + } + this.getImage(); + } + ngOnInit(): void { - const user = new User(this.user); - this.backgroundImage = `url(${user.getUserImageURL()})`; - this.width = this.size; - this.height = this.size; - this.borderRadius = '50%'; + this.getImage(); + } + + getImage() { + if (this.user) { + const user = new User(this.user); + this.backgroundImage = `url(${user.getUserImageURL()})`; + this.width = this.size; + this.height = this.size; + this.borderRadius = '50%'; + } } } diff --git a/app/webFrontend/src/app/shared/modules/material-import.module.ts b/app/webFrontend/src/app/shared/modules/material-import.module.ts index d2deb7974..f5140acca 100644 --- a/app/webFrontend/src/app/shared/modules/material-import.module.ts +++ b/app/webFrontend/src/app/shared/modules/material-import.module.ts @@ -9,7 +9,7 @@ import { MatProgressBarModule, MatRadioModule, MatSelectModule, MatSlideToggleModule, MatSnackBarModule, MatTabsModule, - MatToolbarModule, MatTooltipModule, MatExpansionModule, DateAdapter, MatProgressSpinnerModule + MatToolbarModule, MatTooltipModule, MatExpansionModule, DateAdapter, MatProgressSpinnerModule, MatChipsModule } from '@angular/material'; import {CustomDateAdapter} from '../classes/CustomDateAdapter'; @@ -37,6 +37,7 @@ import {CustomDateAdapter} from '../classes/CustomDateAdapter'; MatToolbarModule, MatTooltipModule, MatProgressSpinnerModule, + MatChipsModule, ], exports: [ MatAutocompleteModule, @@ -61,6 +62,7 @@ import {CustomDateAdapter} from '../classes/CustomDateAdapter'; MatToolbarModule, MatTooltipModule, MatProgressSpinnerModule, + MatChipsModule, ], providers: [ {provide: DateAdapter, useClass: CustomDateAdapter}, diff --git a/app/webFrontend/src/app/shared/services/authentication.service.ts b/app/webFrontend/src/app/shared/services/authentication.service.ts index 8bb66e737..9326b045d 100644 --- a/app/webFrontend/src/app/shared/services/authentication.service.ts +++ b/app/webFrontend/src/app/shared/services/authentication.service.ts @@ -86,6 +86,25 @@ export class AuthenticationService { } + resendActivation(lastname: string, uid: string, email: string) { + return new Promise((resolve, reject) => { + + return this.http.post( + AuthenticationService.API_URL + 'auth/activationresend', + {lastname: lastname, + uid: uid, + email: email} + ) + .subscribe( + (json) => { + resolve(); + }, (err) => { + reject(err); + }); + }); + + } + activate(token: string) { return new Promise((resolve, reject) => { diff --git a/app/webFrontend/src/app/shared/services/backend.service.ts b/app/webFrontend/src/app/shared/services/backend.service.ts index c802ce3c1..045039bab 100644 --- a/app/webFrontend/src/app/shared/services/backend.service.ts +++ b/app/webFrontend/src/app/shared/services/backend.service.ts @@ -24,7 +24,7 @@ export class BackendService { } return Observable.throw(err); - }; + } get(serviceUrl: string): Observable { return this.http.get(BackendService.API_URL + serviceUrl, {headers: this.authenticationService.authHeader()}) diff --git a/app/webFrontend/src/app/shared/services/data.service.ts b/app/webFrontend/src/app/shared/services/data.service.ts index 1489131b1..6981b9c15 100644 --- a/app/webFrontend/src/app/shared/services/data.service.ts +++ b/app/webFrontend/src/app/shared/services/data.service.ts @@ -10,6 +10,7 @@ import {IDownload} from '../../../../../../shared/models/IDownload'; import {IDirectory} from '../../../../../../shared/models/mediaManager/IDirectory'; import {IFile} from '../../../../../../shared/models/mediaManager/IFile'; import {IUserSearchMeta} from '../../../../../../shared/models/IUserSearchMeta'; +import {IConfig} from '../../../../../../shared/models/IConfig'; export abstract class DataService { @@ -63,9 +64,9 @@ export abstract class DataService { .toPromise(); } - readSingleItem(id: string): Promise { + readSingleItem(id: string, apiPath = this.apiPath): Promise { return new Promise((resolve, reject) => { - this.backendService.get(this.apiPath + id) + this.backendService.get(apiPath + id) .subscribe( (responseItems: any) => { if (this.changeProps2Date) { @@ -218,7 +219,7 @@ export class CourseService extends DataService { super('courses/', backendService); } - enrollStudent(courseId: string, data: any): Promise { + enrollStudent(courseId: string, data: any): Promise<{}> { const accessKey: string = data.accessKey; return this.backendService .post(this.apiPath + courseId + '/enroll', JSON.stringify({accessKey})) @@ -231,11 +232,19 @@ export class CourseService extends DataService { .toPromise(); } - leaveStudent(courseId: string): Promise { - return this.backendService + async leaveStudent(courseId: string): Promise<{}> { + return await this.backendService .post(this.apiPath + courseId + '/leave', {}) .toPromise(); } + + readCourseToView(id: string): Promise { + return this.readSingleItem(id); + } + + readCourseToEdit(id: string): Promise { + return this.readSingleItem(id + '/edit'); + } } @Injectable() @@ -477,7 +486,18 @@ export class DownloadFileService extends DataService { @Injectable() export class ConfigService extends DataService { + downloadMaxFileSize: number; constructor(public backendService: BackendService) { super('config/', backendService); } + + async getDownloadMaxFileSize () { + const res = await this.readSingleItem('public/downloadMaxFileSize'); + const _value = Number.parseInt(res.value); + const value = isNaN(_value) ? 51200 : _value; + this.downloadMaxFileSize = value; + + return value; + } + } diff --git a/app/webFrontend/src/app/shared/services/data/progress.service.ts b/app/webFrontend/src/app/shared/services/data/progress.service.ts index 08183d401..2e4de0da1 100644 --- a/app/webFrontend/src/app/shared/services/data/progress.service.ts +++ b/app/webFrontend/src/app/shared/services/data/progress.service.ts @@ -8,12 +8,9 @@ export class ProgressService extends DataService { super('progress/', backendService); } - getUnitProgress(unitId: string) { - const originalApiPath = this.apiPath; - this.apiPath += 'units/'; - const promise = this.readSingleItem(unitId); - this.apiPath = originalApiPath; - return promise; + async getUnitProgress(unitId: string): Promise { + const unitProgress = await this.readSingleItem(unitId, this.apiPath + 'units/'); + return unitProgress.length > 0 ? unitProgress[0] : null; } getCourseProgress(courseId: string) { diff --git a/app/webFrontend/src/app/shared/services/dialog.service.ts b/app/webFrontend/src/app/shared/services/dialog.service.ts index ff71ba75b..104898a9f 100644 --- a/app/webFrontend/src/app/shared/services/dialog.service.ts +++ b/app/webFrontend/src/app/shared/services/dialog.service.ts @@ -8,6 +8,8 @@ import {InfoDialog} from '../components/info-dialog/info-dialog.component'; import {FilepickerDialog} from '../components/filepicker-dialog/filepicker-dialog.component'; import {WriteMailDialog} from '../components/write-mail-dialog/write-mail-dialog.component'; import {ChangePasswordDialogComponent} from '../components/change-password-dialog/change-password-dialog.component'; +import {UserProfileDialog} from '../components/user-profile-dialog/user-profile-dialog.component'; +import {User} from '../../models/User'; @Injectable() export class DialogService { @@ -25,6 +27,15 @@ export class DialogService { return dialogRef.afterClosed(); } + public userProfile(user: User): Observable { + let dialogRef: MatDialogRef; + + dialogRef = this.dialog.open(UserProfileDialog); + dialogRef.componentInstance.user = user; + + return dialogRef.afterClosed(); + } + public confirm(title: string, message: string, confirmText: string = 'Confirm'): Observable { let dialogRef: MatDialogRef; diff --git a/app/webFrontend/src/app/shared/services/imprint-and-info.service.spec.ts b/app/webFrontend/src/app/shared/services/imprint-and-info.service.spec.ts new file mode 100644 index 000000000..33a3685af --- /dev/null +++ b/app/webFrontend/src/app/shared/services/imprint-and-info.service.spec.ts @@ -0,0 +1,15 @@ +import { TestBed, inject } from '@angular/core/testing'; + +import { ImprintAndInfoService } from './imprint-and-info.service'; + +describe('ImprintAndInfoService', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ImprintAndInfoService] + }); + }); + + it('should be created', inject([ImprintAndInfoService], (service: ImprintAndInfoService) => { + expect(service).toBeTruthy(); + })); +}); diff --git a/app/webFrontend/src/app/shared/services/imprint-and-info.service.ts b/app/webFrontend/src/app/shared/services/imprint-and-info.service.ts new file mode 100644 index 000000000..c6b931359 --- /dev/null +++ b/app/webFrontend/src/app/shared/services/imprint-and-info.service.ts @@ -0,0 +1,30 @@ +import { Injectable } from '@angular/core'; +import {IConfig} from '../../../../../../shared/models/IConfig'; +import {MarkdownService} from './markdown.service'; +import {ConfigService} from './data.service'; + +@Injectable() +export class ImprintAndInfoService { + constructor(private service: ConfigService, + private mdService: MarkdownService) { } + + /** + * @param {string} type Should be 'infoBox' to load the InfoBox Data |'imprint' to load the Imprint Data. + * @returns {Promise} Returns the rendered MarkdownData. + */ + async loadConfig(type: string) { + let configRendered = ''; + try { + const config: IConfig = await this.service.readSingleItem('public/' + type); + configRendered = this.renderHtml(config); + } catch (error) { + configRendered = ''; + } + return configRendered; + } + + renderHtml(config: IConfig): string { + return this.mdService.render(config.value) || 'No Content yet!'; + } + +} diff --git a/app/webFrontend/src/app/shared/services/snack-bar.service.spec.ts b/app/webFrontend/src/app/shared/services/snack-bar.service.spec.ts new file mode 100644 index 000000000..4f257cf74 --- /dev/null +++ b/app/webFrontend/src/app/shared/services/snack-bar.service.spec.ts @@ -0,0 +1,50 @@ +/* tslint:disable:no-unused-variable */ + +import {TestBed} from '@angular/core/testing'; +import {SnackBarService} from './snack-bar.service'; +import {MatSnackBar} from '@angular/material'; + +describe('SnackBarService', () => { + + beforeEach(() => { + const matSnackBarSpy = jasmine.createSpyObj('MatSnackBar', ['open']); + + TestBed.configureTestingModule({ + providers: [ + SnackBarService, + {provide: MatSnackBar, useValue: matSnackBarSpy} + ] + }); + }); + + it('should have been called with dismiss and default duration', () => { + const matSnackBar: MatSnackBar = TestBed.get(MatSnackBar); + + const snackBar: SnackBarService = TestBed.get(SnackBarService); + snackBar.open('awesome message'); + + expect(matSnackBar.open) + .toHaveBeenCalledWith('awesome message', SnackBarService.defaultAction, {duration: SnackBarService.defaultDuration}); + }); + + it('should have been called with dismiss and short duration', () => { + const matSnackBar: MatSnackBar = TestBed.get(MatSnackBar); + + const snackBar: SnackBarService = TestBed.get(SnackBarService); + snackBar.openShort('awesome short message'); + + expect(matSnackBar.open) + .toHaveBeenCalledWith('awesome short message', SnackBarService.defaultAction, {duration: SnackBarService.durationShort}); + }); + + it('should have been called with dismiss and long duration', () => { + const matSnackBar: MatSnackBar = TestBed.get(MatSnackBar); + + const snackBar: SnackBarService = TestBed.get(SnackBarService); + snackBar.openLong('awesome long message'); + + expect(matSnackBar.open) + .toHaveBeenCalledWith('awesome long message', SnackBarService.defaultAction, {duration: SnackBarService.durationLong}); + }); + +}); diff --git a/app/webFrontend/src/app/shared/services/snack-bar.service.ts b/app/webFrontend/src/app/shared/services/snack-bar.service.ts new file mode 100644 index 000000000..8ed8d80ff --- /dev/null +++ b/app/webFrontend/src/app/shared/services/snack-bar.service.ts @@ -0,0 +1,50 @@ +import {Injectable} from '@angular/core'; +import {MatSnackBar} from '@angular/material'; +import {MatSnackBarRef} from '@angular/material/snack-bar/typings/snack-bar-ref'; +import {SimpleSnackBar} from '@angular/material/snack-bar/typings/simple-snack-bar'; + +@Injectable() +export class SnackBarService { + + public static readonly durationShort = 3000; + public static readonly durationLong = 9000; + + public static readonly defaultAction = 'Dismiss'; + public static readonly defaultDuration = 6000; + + /** + * @param {MatSnackBar} matSnackBar + */ + constructor(private matSnackBar: MatSnackBar) { + } + + /** + * Return snackbar object with given duration + * @param {string} message + * @param {number} duration + * @returns {MatSnackBarRef} + */ + open(message: string, duration: number = SnackBarService.defaultDuration): MatSnackBarRef { + return this.matSnackBar.open(message, SnackBarService.defaultAction, { + duration: duration + }); + } + + /** + * Return snackbar object with duration short + * @param {string} message + * @returns {MatSnackBarRef} + */ + openShort(message: string): MatSnackBarRef { + return this.open(message, SnackBarService.durationShort); + } + + /** + * Return snackbar object with duration long + * @param {string} message + * @returns {MatSnackBarRef} + */ + openLong(message: string): MatSnackBarRef { + return this.open(message, SnackBarService.durationLong); + } +} diff --git a/app/webFrontend/src/app/shared/services/user.service.ts b/app/webFrontend/src/app/shared/services/user.service.ts index 5ff5e51f3..326305674 100644 --- a/app/webFrontend/src/app/shared/services/user.service.ts +++ b/app/webFrontend/src/app/shared/services/user.service.ts @@ -57,7 +57,7 @@ export class UserService { return true; } - return ( course.teachers.filter(teacher => teacher._id === this.user._id).length) + return ( course.teachers.filter(teacher => teacher._id === this.user._id).length); } isMemberOfCourse(course: ICourse) { diff --git a/app/webFrontend/src/app/shared/shared.module.ts b/app/webFrontend/src/app/shared/shared.module.ts index 84bac61db..730dc8032 100644 --- a/app/webFrontend/src/app/shared/shared.module.ts +++ b/app/webFrontend/src/app/shared/shared.module.ts @@ -21,6 +21,10 @@ import {MarkdownEditorComponent} from './components/markdown-editor/markdown-edi import {AceEditorModule} from 'ng2-ace-editor'; import {PickMediaDialog} from './components/pick-media-dialog/pick-media-dialog.component'; import {TranslateModule} from '@ngx-translate/core'; +import {AdminMarkdownEditComponent} from './components/admin-markdown-edit/admin-markdown-edit.component'; +import {ImprintAndInfoService} from './services/imprint-and-info.service'; +import {UserProfileDialog} from 'app/shared/components/user-profile-dialog/user-profile-dialog.component'; +import {NotfoundComponent} from './components/notfound/notfound.component'; @NgModule({ imports: [ @@ -50,6 +54,10 @@ import {TranslateModule} from '@ngx-translate/core'; ChangePasswordDialogComponent, MarkdownEditorComponent, PickMediaDialog, + AdminMarkdownEditComponent, + UserProfileDialog, + NotfoundComponent, + UserProfileDialog, ], exports: [ GravatarDirective, @@ -70,10 +78,13 @@ import {TranslateModule} from '@ngx-translate/core'; ChangePasswordDialogComponent, PickMediaDialog, TranslateModule, + AdminMarkdownEditComponent, + UserProfileDialog, ], entryComponents: [ UploadFormDialog, PickMediaDialog, + UserProfileDialog, ], }) export class SharedModule { diff --git a/app/webFrontend/src/app/shared/utils/SortUtil.ts b/app/webFrontend/src/app/shared/utils/SortUtil.ts index 2ea6a8159..56a8e02a6 100644 --- a/app/webFrontend/src/app/shared/utils/SortUtil.ts +++ b/app/webFrontend/src/app/shared/utils/SortUtil.ts @@ -16,6 +16,17 @@ export class SortUtil { }); return 0; } + public static sortAlphabetically(array: T[], key: K) { + array.sort((objectA: T, objectB: T) => { + const nameA = objectA[key].toLowerCase(); + const nameB = objectB[key].toLowerCase(); + return (nameA < nameB) ? -1 : ((nameA > nameB) ? 1 : 0); + }); + } + + public static sortCoursesByName(courses: {name: string}[]) { + this.sortAlphabetically(courses, 'name'); + } public static sortByLastVisitedCourses(courses, lastVisitedCourses) { courses.sort((a, b) => { diff --git a/app/webFrontend/src/app/shared/validators/validators.ts b/app/webFrontend/src/app/shared/validators/validators.ts index 24a67f926..ca2d28a19 100644 --- a/app/webFrontend/src/app/shared/validators/validators.ts +++ b/app/webFrontend/src/app/shared/validators/validators.ts @@ -1,4 +1,4 @@ -import {FormGroup} from '@angular/forms'; +import {FormControl, FormGroup} from '@angular/forms'; export function matchPasswords(passwordKey: string, confirmPasswordKey: string) { return (group: FormGroup): { [key: string]: any } => { @@ -12,3 +12,21 @@ export function matchPasswords(passwordKey: string, confirmPasswordKey: string) } }; } + +/** + * A custom email validator which, in comparison to the default angular email validator, + * also checks if the email address has a top-level domain. + * + * @param {FormControl} formControl + * @returns {{emailValidator: {valid: boolean}}} + */ +export function emailValidator(formControl: FormControl) { + // Email Regex from: http://emailregex.com/ + // tslint:disable-next-line:max-line-length + const EMAIL_REGEX = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return EMAIL_REGEX.test(formControl.value) ? null : { + emailValidator: { + valid: false + } + }; +} diff --git a/app/webFrontend/src/app/start/dashboard/dashboard-admin/dashboard-admin.component.ts b/app/webFrontend/src/app/start/dashboard/dashboard-admin/dashboard-admin.component.ts index 2b2a9c5ac..f7a757aeb 100644 --- a/app/webFrontend/src/app/start/dashboard/dashboard-admin/dashboard-admin.component.ts +++ b/app/webFrontend/src/app/start/dashboard/dashboard-admin/dashboard-admin.component.ts @@ -1,6 +1,6 @@ import {Component} from '@angular/core'; import {DashboardBaseComponent} from '../dashboard-base-component'; -import {MatSnackBar} from '@angular/material'; +import {SnackBarService} from '../../../shared/services/snack-bar.service'; import {DialogService} from '../../../shared/services/dialog.service'; import {Router} from '@angular/router'; @@ -13,7 +13,7 @@ export class DashboardAdminComponent extends DashboardBaseComponent { fabOpen = false; - constructor(private snackBar: MatSnackBar, + constructor(private snackBar: SnackBarService, private router: Router, private dialogService: DialogService) { super(); @@ -24,11 +24,11 @@ export class DashboardAdminComponent extends DashboardBaseComponent { closeFab = () => { this.fabOpen = false; - }; + } onFabClick = () => { this.fabOpen = !this.fabOpen; - }; + } onImportCourse = () => { this.dialogService @@ -36,12 +36,12 @@ export class DashboardAdminComponent extends DashboardBaseComponent { '/api/import/course/') .subscribe(res => { if (res.success) { - this.snackBar.open('Course successfully imported', '', {duration: 3000}); + this.snackBar.open('Course successfully imported'); const url = '/course/' + res.result._id + '/edit'; this.router.navigate([url]); } else if (res.result) { - this.snackBar.open(res.result.message, '', {duration: 3000}); + this.snackBar.open(res.result.message); } }); - }; + } } diff --git a/app/webFrontend/src/app/start/dashboard/dashboard-base-component.ts b/app/webFrontend/src/app/start/dashboard/dashboard-base-component.ts index 21d19c976..0b2e44e49 100644 --- a/app/webFrontend/src/app/start/dashboard/dashboard-base-component.ts +++ b/app/webFrontend/src/app/start/dashboard/dashboard-base-component.ts @@ -1,10 +1,10 @@ import {OnInit, Input, Output, EventEmitter} from '@angular/core'; -import {ICourse} from '../../../../../../shared/models/ICourse'; +import {ICourseDashboard} from '../../../../../../shared/models/ICourseDashboard'; export abstract class DashboardBaseComponent implements OnInit { @Input() - allCourses: ICourse[]; + allCourses: ICourseDashboard[]; @Output() onEnroll = new EventEmitter(); diff --git a/app/webFrontend/src/app/start/dashboard/dashboard-student/dashboard-student.component.html b/app/webFrontend/src/app/start/dashboard/dashboard-student/dashboard-student.component.html index 6c7d8d758..37e7107e3 100644 --- a/app/webFrontend/src/app/start/dashboard/dashboard-student/dashboard-student.component.html +++ b/app/webFrontend/src/app/start/dashboard/dashboard-student/dashboard-student.component.html @@ -1,2 +1,8 @@ + + + last visited + alphabetically + + diff --git a/app/webFrontend/src/app/start/dashboard/dashboard-student/dashboard-student.component.scss b/app/webFrontend/src/app/start/dashboard/dashboard-student/dashboard-student.component.scss index e9de61fb6..5d56ed40a 100644 --- a/app/webFrontend/src/app/start/dashboard/dashboard-student/dashboard-student.component.scss +++ b/app/webFrontend/src/app/start/dashboard/dashboard-student/dashboard-student.component.scss @@ -4,3 +4,12 @@ flex-wrap: wrap; } + + +@media screen and (max-width: 475px){ + .pull-right{ + float: none; + } +} + + diff --git a/app/webFrontend/src/app/start/dashboard/dashboard-student/dashboard-student.component.ts b/app/webFrontend/src/app/start/dashboard/dashboard-student/dashboard-student.component.ts index dd68127ac..3c2a15bb9 100644 --- a/app/webFrontend/src/app/start/dashboard/dashboard-student/dashboard-student.component.ts +++ b/app/webFrontend/src/app/start/dashboard/dashboard-student/dashboard-student.component.ts @@ -1,5 +1,5 @@ import {Component} from '@angular/core'; -import {ICourse} from '../../../../../../../shared/models/ICourse'; +import {ICourseDashboard} from '../../../../../../../shared/models/ICourseDashboard'; import {UserService} from '../../../shared/services/user.service'; import {DashboardBaseComponent} from '../dashboard-base-component'; import {SortUtil} from '../../../shared/utils/SortUtil'; @@ -12,8 +12,8 @@ import {SortUtil} from '../../../shared/utils/SortUtil'; }) export class DashboardStudentComponent extends DashboardBaseComponent { - myCourses: ICourse[]; - availableCourses: ICourse[]; + myCourses: ICourseDashboard[]; + availableCourses: ICourseDashboard[]; constructor(public userService: UserService) { super(); @@ -25,6 +25,10 @@ export class DashboardStudentComponent extends DashboardBaseComponent { ngOnChanges() { this.sortCourses(); } + async sortAlphabetically() { + SortUtil.sortCoursesByName(this.myCourses); + SortUtil.sortCoursesByName(this.availableCourses); + } async sortCourses() { this.myCourses = []; @@ -32,16 +36,11 @@ export class DashboardStudentComponent extends DashboardBaseComponent { SortUtil.sortByLastVisitedCourses(this.allCourses, this.userService.user.lastVisitedCourses); for (const course of this.allCourses) { - if (this.userService.isMemberOfCourse(course)) { + if (course.userCanViewCourse) { this.myCourses.push(course); } else { this.availableCourses.push(course); } } } - - isMemberOfCourse(course: ICourse) { - const user = this.userService.user; - return course.students.filter(obj => obj._id === user._id).length > 0; - } } diff --git a/app/webFrontend/src/app/start/dashboard/dashboard-teacher/dashboard-teacher.component.ts b/app/webFrontend/src/app/start/dashboard/dashboard-teacher/dashboard-teacher.component.ts index cb2ddeb09..c1dd801ec 100644 --- a/app/webFrontend/src/app/start/dashboard/dashboard-teacher/dashboard-teacher.component.ts +++ b/app/webFrontend/src/app/start/dashboard/dashboard-teacher/dashboard-teacher.component.ts @@ -1,8 +1,8 @@ import {Component} from '@angular/core'; -import {ICourse} from '../../../../../../../shared/models/ICourse'; +import {ICourseDashboard} from '../../../../../../../shared/models/ICourseDashboard'; import {UserService} from '../../../shared/services/user.service'; import {DashboardBaseComponent} from '../dashboard-base-component'; -import {MatSnackBar} from '@angular/material'; +import {SnackBarService} from '../../../shared/services/snack-bar.service'; import {Router} from '@angular/router'; import {DialogService} from '../../../shared/services/dialog.service'; import {SortUtil} from '../../../shared/utils/SortUtil'; @@ -14,16 +14,16 @@ import {SortUtil} from '../../../shared/utils/SortUtil'; }) export class DashboardTeacherComponent extends DashboardBaseComponent { - myCourses: ICourse[]; - furtherCourses: ICourse[]; - inactiveCourses: ICourse[]; - availableCourses: ICourse[]; + myCourses: ICourseDashboard[]; + furtherCourses: ICourseDashboard[]; + inactiveCourses: ICourseDashboard[]; + availableCourses: ICourseDashboard[]; fabOpen = false; constructor(public userService: UserService, private router: Router, private dialogService: DialogService, - private snackBar: MatSnackBar) { + private snackBar: SnackBarService) { super(); } @@ -38,46 +38,39 @@ export class DashboardTeacherComponent extends DashboardBaseComponent { this.inactiveCourses = []; SortUtil.sortByLastVisitedCourses(this.allCourses, this.userService.user.lastVisitedCourses); for (const course of this.allCourses) { - if ((this.filterMyCourses(course) || this.filterAdminCourses(course)) && !course.active) { - this.inactiveCourses.push(course); - } else if (this.filterAdminCourses(course)) { - this.myCourses.push(course); - } else if (this.filterMyCourses(course)) { - this.furtherCourses.push(course); + if (course.userIsCourseAdmin || course.userIsCourseTeacher) { + if (!course.active) { + this.inactiveCourses.push(course); + } else if (course.userIsCourseAdmin) { + this.myCourses.push(course); + } else { + this.furtherCourses.push(course); + } } else { this.availableCourses.push(course); } } } - filterAdminCourses(course: ICourse) { - return (course.courseAdmin._id === this.userService.user._id); - } - - filterMyCourses(course: ICourse) { - return (course.teachers.filter(teacher => teacher._id === this.userService.user._id).length); - } - closeFab = () => { this.fabOpen = false; - }; + } onFabClick = () => { this.fabOpen = !this.fabOpen; - }; + } onImportCourse = () => { this.dialogService - .chooseFile('Choose a course.json to import', - '/api/import/course/') + .chooseFile('Choose a course.json to import', '/api/import/course/') .subscribe(res => { if (res.success) { - this.snackBar.open('Course successfully imported', '', {duration: 3000}); + this.snackBar.open('Course successfully imported'); const url = '/course/' + res.result._id + '/edit'; this.router.navigate([url]); } else if (res.result) { - this.snackBar.open(res.result.message, '', {duration: 3000}); + this.snackBar.open(res.result.message); } }); - }; + } } diff --git a/app/webFrontend/src/app/start/dashboard/dashboard.component.ts b/app/webFrontend/src/app/start/dashboard/dashboard.component.ts index c83d46cd8..f99a02dd1 100644 --- a/app/webFrontend/src/app/start/dashboard/dashboard.component.ts +++ b/app/webFrontend/src/app/start/dashboard/dashboard.component.ts @@ -1,5 +1,5 @@ import {Component, OnInit} from '@angular/core'; -import {ICourse} from '../../../../../../shared/models/ICourse'; +import {ICourseDashboard} from '../../../../../../shared/models/ICourseDashboard'; import {UserService} from '../../shared/services/user.service'; import {CourseService} from '../../shared/services/data.service'; import {TitleService} from '../../shared/services/title.service'; @@ -11,7 +11,7 @@ import {TitleService} from '../../shared/services/title.service'; }) export class DashboardComponent implements OnInit { - allCourses: ICourse[]; + allCourses: ICourseDashboard[]; // UserService for HTML page constructor(private courseService: CourseService, @@ -25,13 +25,11 @@ export class DashboardComponent implements OnInit { this.getCourses(); } - getCourses() { - this.courseService.readItems().then(courses => { - this.allCourses = courses; - }); + async getCourses() { + this.allCourses = await this.courseService.readItems(); } onUpdateCallback() { - this.getCourses(); + this.getCourses(); } } diff --git a/app/webFrontend/src/app/start/homescreen/homescreen.component.html b/app/webFrontend/src/app/start/homescreen/homescreen.component.html index 8912e8fc6..f87d47923 100644 --- a/app/webFrontend/src/app/start/homescreen/homescreen.component.html +++ b/app/webFrontend/src/app/start/homescreen/homescreen.component.html @@ -1 +1,2 @@

{{'home.welcomeTo'|translate}} {{'common.geli'|translate}}!

+ diff --git a/app/webFrontend/src/app/start/homescreen/homescreen.component.scss b/app/webFrontend/src/app/start/homescreen/homescreen.component.scss index 074c9f12b..5096670b6 100644 --- a/app/webFrontend/src/app/start/homescreen/homescreen.component.scss +++ b/app/webFrontend/src/app/start/homescreen/homescreen.component.scss @@ -4,13 +4,15 @@ flex-grow: 1; display: flex; justify-content: center; - align-items: center; + align-items: flex-end; } h1 { color: white; text-align: center; text-shadow: 0 0 5px gray; + position: absolute; + bottom: 50%; } .logo-font { diff --git a/app/webFrontend/src/app/start/homescreen/info-box/info-box.component.html b/app/webFrontend/src/app/start/homescreen/info-box/info-box.component.html new file mode 100644 index 000000000..c4c3134e8 --- /dev/null +++ b/app/webFrontend/src/app/start/homescreen/info-box/info-box.component.html @@ -0,0 +1,3 @@ + + diff --git a/app/webFrontend/src/app/start/homescreen/info-box/info-box.component.scss b/app/webFrontend/src/app/start/homescreen/info-box/info-box.component.scss new file mode 100644 index 000000000..d3685e6e7 --- /dev/null +++ b/app/webFrontend/src/app/start/homescreen/info-box/info-box.component.scss @@ -0,0 +1,9 @@ +.infoBox { + display: flex; + max-width: 600px; + width: 100%; + padding: 1em; + flex-direction: column; + background-color: rgba(255 ,255 ,255 ,0.9); + color: black; +} diff --git a/app/webFrontend/src/app/start/homescreen/info-box/info-box.component.spec.ts b/app/webFrontend/src/app/start/homescreen/info-box/info-box.component.spec.ts new file mode 100644 index 000000000..d3627294c --- /dev/null +++ b/app/webFrontend/src/app/start/homescreen/info-box/info-box.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { InfoBoxComponent } from './info-box.component'; + +describe('InfoBoxComponent', () => { + let component: InfoBoxComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ InfoBoxComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(InfoBoxComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/webFrontend/src/app/start/homescreen/info-box/info-box.component.ts b/app/webFrontend/src/app/start/homescreen/info-box/info-box.component.ts new file mode 100644 index 000000000..b428513c2 --- /dev/null +++ b/app/webFrontend/src/app/start/homescreen/info-box/info-box.component.ts @@ -0,0 +1,21 @@ +import {Component, OnInit} from '@angular/core'; +import {ImprintAndInfoService} from '../../../shared/services/imprint-and-info.service'; + +@Component({ + selector: 'app-info-box', + templateUrl: './info-box.component.html', + styleUrls: ['./info-box.component.scss'] +}) +export class InfoBoxComponent implements OnInit { + contentRendered: string; + + + constructor(private infoBoxService: ImprintAndInfoService) { + } + + ngOnInit() { + this.infoBoxService.loadConfig('infoBox').then((str => { + this.contentRendered = str; + })); + } +} diff --git a/app/webFrontend/src/app/start/start.component.scss b/app/webFrontend/src/app/start/start.component.scss index d8f59cf6b..1e311e585 100644 --- a/app/webFrontend/src/app/start/start.component.scss +++ b/app/webFrontend/src/app/start/start.component.scss @@ -2,3 +2,8 @@ flex-grow: 1; display: flex; } + +app-dashboard +{ + width: 100%; +} diff --git a/app/webFrontend/src/app/start/start.module.ts b/app/webFrontend/src/app/start/start.module.ts index 985a192ce..02cf3860f 100644 --- a/app/webFrontend/src/app/start/start.module.ts +++ b/app/webFrontend/src/app/start/start.module.ts @@ -10,6 +10,7 @@ import {RouterModule} from '@angular/router'; import {CourseModule} from '../course/course.module'; import {SharedModule} from '../shared/shared.module'; import {NotificationModule} from '../notification/notification.module'; +import {InfoBoxComponent} from './homescreen/info-box/info-box.component'; @NgModule({ imports: [ @@ -25,6 +26,7 @@ import {NotificationModule} from '../notification/notification.module'; DashboardStudentComponent, DashboardTeacherComponent, DashboardAdminComponent, + InfoBoxComponent, ], exports: [ StartComponent, diff --git a/app/webFrontend/src/app/unit/code-kata-unit/code-kata-unit.component.html b/app/webFrontend/src/app/unit/code-kata-unit/code-kata-unit.component.html index 3df1b6690..316db517a 100644 --- a/app/webFrontend/src/app/unit/code-kata-unit/code-kata-unit.component.html +++ b/app/webFrontend/src/app/unit/code-kata-unit/code-kata-unit.component.html @@ -31,6 +31,8 @@ -
Logs
-
{{logs}}
+
+ Logs: +
{{logs}}
+
diff --git a/app/webFrontend/src/app/unit/code-kata-unit/code-kata-unit.component.scss b/app/webFrontend/src/app/unit/code-kata-unit/code-kata-unit.component.scss index 8ea7b7701..b1b746ca4 100644 --- a/app/webFrontend/src/app/unit/code-kata-unit/code-kata-unit.component.scss +++ b/app/webFrontend/src/app/unit/code-kata-unit/code-kata-unit.component.scss @@ -2,9 +2,19 @@ ace-editor { margin-top: 0.5em; margin-bottom: 1em; margin-left: 1em; - width: 90%; + width: calc(100% - 1em); } .user-code-editor { min-height: 15em; } + +.logs-title { + margin-top: 0.5em; +} + +pre { + margin-top: 0.5em; + margin-left: 1em; + font-size: 0.9em; +} diff --git a/app/webFrontend/src/app/unit/code-kata-unit/code-kata-unit.component.ts b/app/webFrontend/src/app/unit/code-kata-unit/code-kata-unit.component.ts index 5f36e6ad0..0694f0dcc 100644 --- a/app/webFrontend/src/app/unit/code-kata-unit/code-kata-unit.component.ts +++ b/app/webFrontend/src/app/unit/code-kata-unit/code-kata-unit.component.ts @@ -1,5 +1,5 @@ import {Component, Input, OnInit, ViewChild} from '@angular/core'; -import {MatSnackBar} from '@angular/material'; +import {SnackBarService} from '../../shared/services/snack-bar.service'; import {ProgressService} from 'app/shared/services/data/progress.service'; import {ICodeKataUnitProgress} from '../../../../../../shared/models/progress/ICodeKataProgress'; import {UserService} from '../../shared/services/user.service'; @@ -31,7 +31,7 @@ export class CodeKataComponent implements OnInit { isExampleCode = false; constructor(private route: ActivatedRoute, - private snackBar: MatSnackBar, + private snackBar: SnackBarService, private progressService: ProgressService, private userService: UserService) { this.logs = undefined; @@ -46,6 +46,15 @@ export class CodeKataComponent implements OnInit { this.progress = this.codeKataUnit.progressData; } } + + this.applyProgressData(); + } + + async applyProgressData() { + const progress = await this.progressService.getUnitProgress(this.codeKataUnit._id); + if (progress) { + this.progress = progress; + } } ngAfterViewInit() { @@ -62,34 +71,35 @@ export class CodeKataComponent implements OnInit { }); this.testEditor.setOptions({ maxLines: 9999, - firstLineNumber: ((this.codeKataUnit.definition.split('\n').length) || 0) + 1, + firstLineNumber: ((this.codeKataUnit.definition.split('\n').length || 0) + + (this.codeEditor.text.split('\n').length || 0) + 1), }); } async submitProgress() { this.progress.done = this.validate(); if (!this.progress.done) { - this.snackBar.open('Your code does not validate.', '', {duration: 3000}); + this.snackBar.open('Your code does not validate.'); } if (!this.progress._id) { this.progress.user = this.userService.user._id; this.progressService.createItem(this.progress) .then((item) => { - this.snackBar.open('Progress has been saved', '', {duration: 3000}); + this.snackBar.open('Progress has been saved'); this.progress = item; }) .catch((err) => { - this.snackBar.open(`An error occurred: ${err.json().message}`, '', {duration: 3000}); + this.snackBar.open(`An error occurred: ${err.error.message}`); }); } else { this.progressService.updateItem(this.progress) .then((item) => { - this.snackBar.open('Progress has been updated', '', {duration: 3000}); + this.snackBar.open('Progress has been updated'); this.progress = item; }) .catch((err) => { - this.snackBar.open(`An error occurred: ${err.json().message}`, '', {duration: 3000}) + this.snackBar.open(`An error occurred: ${err.error.message}`); }); } } @@ -130,10 +140,10 @@ export class CodeKataComponent implements OnInit { window.console.log = origLogger; if (result === true || result === undefined) { - this.snackBar.open('Success', '', {duration: 3000}); + this.snackBar.open('Success'); return true; } else { - this.snackBar.open('Your code failed.', '', {duration: 3000}); + this.snackBar.open('Your code failed.'); // tslint:disable-next-line:no-console console.log(result); return false; diff --git a/app/webFrontend/src/app/unit/file-unit/file-unit.component.html b/app/webFrontend/src/app/unit/file-unit/file-unit.component.html index 5848e148c..55f892c31 100644 --- a/app/webFrontend/src/app/unit/file-unit/file-unit.component.html +++ b/app/webFrontend/src/app/unit/file-unit/file-unit.component.html @@ -1,6 +1,7 @@
- + +
diff --git a/app/webFrontend/src/app/unit/file-unit/file-unit.component.scss b/app/webFrontend/src/app/unit/file-unit/file-unit.component.scss index e82d55668..bb0b17fe8 100644 --- a/app/webFrontend/src/app/unit/file-unit/file-unit.component.scss +++ b/app/webFrontend/src/app/unit/file-unit/file-unit.component.scss @@ -1,3 +1,5 @@ +@import '../../../variables'; + .lightbox-cstm--preview { max-height: 10rem; margin: 0 .5rem; diff --git a/app/webFrontend/src/app/unit/file-unit/file-unit.component.ts b/app/webFrontend/src/app/unit/file-unit/file-unit.component.ts index fbae5f5a5..ce1886a5f 100644 --- a/app/webFrontend/src/app/unit/file-unit/file-unit.component.ts +++ b/app/webFrontend/src/app/unit/file-unit/file-unit.component.ts @@ -1,4 +1,4 @@ -import {Component, OnInit, Input} from '@angular/core'; +import {Component, OnInit, Input, ViewChildren, QueryList, Directive, AfterViewInit, ElementRef} from '@angular/core'; import {IFileUnit} from '../../../../../../shared/models/units/IFileUnit'; import {Lightbox, IAlbum} from 'angular2-lightbox'; @@ -8,9 +8,11 @@ import {Lightbox, IAlbum} from 'angular2-lightbox'; styleUrls: ['./file-unit.component.scss'] }) export class FileUnitComponent implements OnInit { - @Input() fileUnit: IFileUnit; album: Array = []; + @ViewChildren('vid') vidChilds: QueryList; + videosLoaded = 0; + smallestVideoSize = 1080; constructor(private lightbox: Lightbox) { } @@ -31,6 +33,26 @@ export class FileUnitComponent implements OnInit { }); } + loadedVideos($event) { + const vidWidth = $event.target.videoWidth; + if (vidWidth < this.smallestVideoSize) { + this.smallestVideoSize = vidWidth; + } + this.videosLoaded += 1; + if (this.videosLoaded === this.fileUnit.files.length) { + if (this.smallestVideoSize > $event.target.parentElement.clientWidth) { + this.smallestVideoSize = $event.target.parentElement.clientWidth; + } + this.setSmallestVideoWidth(this.smallestVideoSize); + } + } + + setSmallestVideoWidth(width: number): void { + this.vidChilds.forEach(vidChild => { + vidChild.nativeElement.width = width; + }); + } + openLB(index: number): void { this.lightbox.open(this.album, index); } @@ -52,5 +74,4 @@ export class FileUnitComponent implements OnInit { const ext = fileName.substr(extPos + 1); return pictureExt.includes(ext); } - } diff --git a/app/webFrontend/src/app/unit/task-unit/task-unit.component.html b/app/webFrontend/src/app/unit/task-unit/task-unit.component.html index 83687c912..e709c295a 100644 --- a/app/webFrontend/src/app/unit/task-unit/task-unit.component.html +++ b/app/webFrontend/src/app/unit/task-unit/task-unit.component.html @@ -6,7 +6,7 @@ [class.correct]="validationMode && answer.value" [class.incorrect]="validationMode && !answer.value"> - + {{answer.text}} diff --git a/app/webFrontend/src/app/unit/task-unit/task-unit.component.ts b/app/webFrontend/src/app/unit/task-unit/task-unit.component.ts index 11f23ead7..77f2614a6 100644 --- a/app/webFrontend/src/app/unit/task-unit/task-unit.component.ts +++ b/app/webFrontend/src/app/unit/task-unit/task-unit.component.ts @@ -33,6 +33,16 @@ export class TaskUnitComponent implements OnInit { this.progress = this.taskUnit.progressData; } + this.applyProgressData(); + this.shuffleAnswers(); + } + + async applyProgressData() { + const progress = await this.progressService.getUnitProgress(this.taskUnit._id); + if (progress) { + this.progress = progress; + } + if (!this.progress.answers) { this.resetProgressAnswers(); } else { @@ -49,7 +59,6 @@ export class TaskUnitComponent implements OnInit { } }); } - this.shuffleAnswers(); } resetProgressAnswers() { @@ -76,7 +85,7 @@ export class TaskUnitComponent implements OnInit { this.snackBar.open('Progress has been saved', '', {duration: 3000}); }) .catch((err) => { - this.snackBar.open(`An error occurred: ${err.json().message}`, '', {duration: 3000}) + this.snackBar.open(`An error occurred: ${err.error.message}`, '', {duration: 3000}); }); }; diff --git a/app/webFrontend/src/app/unit/unit-form/code-kata-unit-form/code-kata-unit-form.component.html b/app/webFrontend/src/app/unit/unit-form/code-kata-unit-form/code-kata-unit-form.component.html index 5b6ca0c1a..6c1262a26 100644 --- a/app/webFrontend/src/app/unit/unit-form/code-kata-unit-form/code-kata-unit-form.component.html +++ b/app/webFrontend/src/app/unit/unit-form/code-kata-unit-form/code-kata-unit-form.component.html @@ -14,7 +14,7 @@ @@ -22,6 +22,8 @@ -
Logs
-
{{logs}}
+
+ Logs: +
{{logs}}
+
diff --git a/app/webFrontend/src/app/unit/unit-form/code-kata-unit-form/code-kata-unit-form.component.scss b/app/webFrontend/src/app/unit/unit-form/code-kata-unit-form/code-kata-unit-form.component.scss index b4eb9e1e6..b1b746ca4 100644 --- a/app/webFrontend/src/app/unit/unit-form/code-kata-unit-form/code-kata-unit-form.component.scss +++ b/app/webFrontend/src/app/unit/unit-form/code-kata-unit-form/code-kata-unit-form.component.scss @@ -2,6 +2,19 @@ ace-editor { margin-top: 0.5em; margin-bottom: 1em; margin-left: 1em; - width: 90%; + width: calc(100% - 1em); +} + +.user-code-editor { min-height: 15em; } + +.logs-title { + margin-top: 0.5em; +} + +pre { + margin-top: 0.5em; + margin-left: 1em; + font-size: 0.9em; +} diff --git a/app/webFrontend/src/app/unit/unit-form/code-kata-unit-form/code-kata-unit-form.component.ts b/app/webFrontend/src/app/unit/unit-form/code-kata-unit-form/code-kata-unit-form.component.ts index 3ca5e2c85..485fc48e8 100644 --- a/app/webFrontend/src/app/unit/unit-form/code-kata-unit-form/code-kata-unit-form.component.ts +++ b/app/webFrontend/src/app/unit/unit-form/code-kata-unit-form/code-kata-unit-form.component.ts @@ -1,6 +1,6 @@ import {Component, Input, OnInit, ViewChild} from '@angular/core'; import {CodeKataUnitService, NotificationService, UnitService} from '../../../shared/services/data.service'; -import {MatSnackBar} from '@angular/material'; +import {SnackBarService} from '../../../shared/services/snack-bar.service'; import {ICodeKataUnit} from '../../../../../../../shared/models/units/ICodeKataUnit'; import {ICourse} from '../../../../../../../shared/models/ICourse'; import {CodeKataUnit} from '../../../models/units/CodeKataUnit'; @@ -53,35 +53,28 @@ export class CodeKataUnitFormComponent implements OnInit { }; logs: string; + wholeInputCode: string; constructor(private codeKataUnitService: CodeKataUnitService, private unitService: UnitService, - private snackBar: MatSnackBar, + private snackBar: SnackBarService, private notificationService: NotificationService) { } ngOnInit() { if (!this.model) { this.model = new CodeKataUnit(this.course._id); - this.model.code = - this.example.definition - + '\n\n' + this.areaSeperator + ' code-section' + ((this.example.code.startsWith('//')) ? '\n' : '\n\n') - + this.example.code - + '\n\n' + this.areaSeperator + ' test-section' + ((this.example.test.startsWith('//')) ? '\n' : '\n\n') - + this.example.test; - this.model.definition = undefined; - this.model.test = undefined; - } else { - this.model.code = - this.model.definition - + '\n\n' + this.areaSeperator + '\n\n' - + this.model.code - + '\n\n' + this.areaSeperator + '\n\n' - + this.model.test; - this.model.definition = undefined; - this.model.test = undefined; + this.model.definition = this.example.definition; + this.model.code = this.example.code; + this.model.test = this.example.test; } + this.wholeInputCode = + this.model.definition + + '\n' + this.areaSeperator + '\n' + + this.model.code + + '\n' + this.areaSeperator + '\n' + + this.model.test; this.editor.getEditor().setOptions({ maxLines: 9999, }); @@ -89,56 +82,65 @@ export class CodeKataUnitFormComponent implements OnInit { addUnit() { if (!this.validate()) { - this.snackBar.open('Your code does not validate. Check logs for information', '', {duration: 3000}); + this.snackBar.open('Your code does not validate. Check logs for information'); } + const inputCodeArray = this.wholeInputCode.split('\n' + this.areaSeperator + '\n'); this.model = { ...this.model, + definition: inputCodeArray[0], + code: inputCodeArray[1], + test: inputCodeArray[2], name: this.generalInfo.form.value.name, description: this.generalInfo.form.value.description, deadline: this.generalInfo.form.value.deadline, + visible: this.generalInfo.form.value.visible }; if (this.model._id === undefined) { - this.unitService.createItem({ + this.createCodeKata(); + } else { + this.updateCodeKata(); + } + } + + private async createCodeKata() { + try { + const unit = await this.unitService.createItem({ model: this.model, lectureId: this.lectureId - }) - .then( - (unit) => { - this.snackBar.open('Code-Kata created', '', {duration: 3000}); - this.onDone(); - return this.notificationService.createItem( - { - changedCourse: this.course, - changedLecture: this.lectureId, - changedUnit: unit, - text: 'Course ' + this.course.name + ' has a new code kata unit.' - }); - }, - (error) => { - const message = error.json().message; - this.snackBar.open('Failed to create Code-Kata => ' + message, '', {duration: 3000}); - }); - } else { + }); + + this.notificationService.createItem({ + changedCourse: this.course, + changedLecture: this.lectureId, + changedUnit: unit, + text: 'Course ' + this.course.name + ' has a new code kata unit.' + }); + + this.snackBar.open('Code-Kata created'); + this.onDone(); + } catch (err) { + this.snackBar.open('Failed to create Code-Kata: ' + err.error.message); + } + } + + private async updateCodeKata() { + try { delete this.model._course; - this.unitService.updateItem(this.model) - .then( - (unit) => { - this.snackBar.open('Code-Kata updated', '', {duration: 3000}); - this.onDone(); - return this.notificationService.createItem( - { - changedCourse: this.course, - changedLecture: this.lectureId, - changedUnit: unit, - text: 'Course ' + this.course.name + ' has an updated unit.' - }); - }, - (error) => { - const message = error.json().message; - this.snackBar.open('Failed to update Code-Kata => ' + message, '', {duration: 3000}); - }); + const unit = await this.unitService.updateItem(this.model); + + this.notificationService.createItem({ + changedCourse: this.course, + changedLecture: this.lectureId, + changedUnit: unit, + text: 'Course ' + this.course.name + ' has an updated unit.' + }); + + this.snackBar.open('Code-Kata updated'); + this.onDone(); + } catch (err) { + this.snackBar.open('Failed to update Code-Kata: ' + err.error.message); } } @@ -147,8 +149,7 @@ export class CodeKataUnitFormComponent implements OnInit { if (!this.validateStructure()) { return false; } - - const codeToTest: string = this.model.code; + const codeToTest: string = this.wholeInputCode; this.logs = undefined; @@ -178,10 +179,8 @@ export class CodeKataUnitFormComponent implements OnInit { window.console.log = origLogger; if (result === true || result === undefined) { - this.snackBar.open('Success', '', {duration: 3000}); return true; } else { - this.snackBar.open('Your code failed.', '', {duration: 3000}); // tslint:disable-next-line:no-console console.log(result); return false; @@ -190,16 +189,25 @@ export class CodeKataUnitFormComponent implements OnInit { // this code gets unnessessary with the Implementation of Issue #44 (all validation parts should happen on the server) private validateStructure(): boolean { - if (!this.model.code.match(new RegExp('function(.|\t)*validate\\(\\)(.|\n|\t)*{(.|\n|\t)*}', 'gmi'))) { - this.snackBar.open('The test section must contain a validate function', 'Dismiss'); + const separatorCount = (this.wholeInputCode.match(new RegExp(this.areaSeperator, 'gmi')) || []).length; + if (separatorCount > 2) { + this.snackBar.open('There are too many area separators'); + return false; + } + if (separatorCount < 2) { + this.snackBar.open('There must be 2 area separators'); + return false; + } + if (!this.wholeInputCode.match(new RegExp('function(.|\t)*validate\\(\\)(.|\n|\t)*{(.|\n|\t)*}', 'gmi'))) { + this.snackBar.open('The test section must contain a validate function'); return false; } - if (!this.model.code.match(new RegExp('function(.|\t)*validate\\(\\)(.|\n|\t)*{(.|\n|\t)*return(.|\n|\t)*}', 'gmi'))) { - this.snackBar.open('The validate function must return something', 'Dismiss'); + if (!this.wholeInputCode.match(new RegExp('function(.|\t)*validate\\(\\)(.|\n|\t)*{(.|\n|\t)*return(.|\n|\t)*}', 'gmi'))) { + this.snackBar.open('The validate function must return something'); return false; } - if (!this.model.code.match(new RegExp('validate\\(\\);', 'gmi'))) { - this.snackBar.open('The test section must call the validate function', 'Dismiss'); + if (!this.wholeInputCode.match(new RegExp('validate\\(\\);', 'gmi'))) { + this.snackBar.open('The test section must call the validate function'); return false; } diff --git a/app/webFrontend/src/app/unit/unit-form/file-unit-form/file-unit-form.component.ts b/app/webFrontend/src/app/unit/unit-form/file-unit-form/file-unit-form.component.ts index 00949a1df..079d7dab7 100644 --- a/app/webFrontend/src/app/unit/unit-form/file-unit-form/file-unit-form.component.ts +++ b/app/webFrontend/src/app/unit/unit-form/file-unit-form/file-unit-form.component.ts @@ -51,7 +51,9 @@ export class FileUnitFormComponent implements OnInit { this.model = { ...this.model, name: this.generalInfo.form.value.name, - description: this.generalInfo.form.value.description + description: this.generalInfo.form.value.description, + visible: this.generalInfo.form.value.visible + }; const reqObj = { diff --git a/app/webFrontend/src/app/unit/unit-form/free-text-unit-form/free-text-unit-form.component.ts b/app/webFrontend/src/app/unit/unit-form/free-text-unit-form/free-text-unit-form.component.ts index 442c8ca18..1578ed9ac 100644 --- a/app/webFrontend/src/app/unit/unit-form/free-text-unit-form/free-text-unit-form.component.ts +++ b/app/webFrontend/src/app/unit/unit-form/free-text-unit-form/free-text-unit-form.component.ts @@ -44,6 +44,8 @@ export class FreeTextUnitFormComponent implements OnInit { ...this.model, name: this.generalInfo.form.value.name, description: this.generalInfo.form.value.description, + visible: this.generalInfo.form.value.visible, + markdown: this.freeTextEditor.markdown }; diff --git a/app/webFrontend/src/app/unit/unit-form/task-unit-edit/task-unit-edit.component.html b/app/webFrontend/src/app/unit/unit-form/task-unit-edit/task-unit-edit.component.html index 4fadbabf6..62954c2cd 100644 --- a/app/webFrontend/src/app/unit/unit-form/task-unit-edit/task-unit-edit.component.html +++ b/app/webFrontend/src/app/unit/unit-form/task-unit-edit/task-unit-edit.component.html @@ -9,7 +9,7 @@
- + {{unit.name}} @@ -18,6 +21,13 @@ +
+
{{unit.unitCreator.profile.firstName + ' ' + + unit.unitCreator.profile.lastName}} +
+ Published on: {{getFormattedDate(unit.createdAt)}} + Changed on: {{getFormattedDate(unit.updatedAt)}} +
diff --git a/app/webFrontend/src/app/unit/unit.component.scss b/app/webFrontend/src/app/unit/unit.component.scss index 597bb2586..b901da82f 100644 --- a/app/webFrontend/src/app/unit/unit.component.scss +++ b/app/webFrontend/src/app/unit/unit.component.scss @@ -23,3 +23,14 @@ .red { color: #F44336 } + +.unit-detail { + font-size: 8pt; + margin-top: 0.2em; + text-align: right; + color: #949699; +} + +.user-detail { + font-style: bold; +} diff --git a/app/webFrontend/src/app/unit/unit.component.ts b/app/webFrontend/src/app/unit/unit.component.ts index dec70e8cc..f18be42b8 100644 --- a/app/webFrontend/src/app/unit/unit.component.ts +++ b/app/webFrontend/src/app/unit/unit.component.ts @@ -2,6 +2,7 @@ import {Component, OnInit, Input, AfterViewInit} from '@angular/core'; import {IUnit} from '../../../../../shared/models/units/IUnit'; import * as moment from 'moment'; import {ActivatedRoute, Router} from '@angular/router'; +import {IUser} from '../../../../../shared/models/IUser'; @Component({ selector: 'app-unit', @@ -12,6 +13,7 @@ export class UnitComponent implements OnInit, AfterViewInit { @Input() units: IUnit[]; unitId: string; + users: IUser[] = []; private getDeadlineDiffTime (deadline: string) { const momentDeadline = moment(deadline); @@ -35,6 +37,10 @@ export class UnitComponent implements OnInit, AfterViewInit { return moment(deadline).format('DD.MM.YYYY HH:mm'); } + private getFormattedDate(date: string) { + return moment(date).format('DD.MM.YYYY'); + } + private selectColorForDeadline(deadline: string) { const diffInHours = moment(deadline).diff(moment(), 'hours'); const diffInDays = moment(deadline).diff(moment(), 'days'); diff --git a/app/webFrontend/src/app/user/user-details/user-details.component.html b/app/webFrontend/src/app/user/user-details/user-details.component.html index 54f82b9f3..99da3cb2d 100644 --- a/app/webFrontend/src/app/user/user-details/user-details.component.html +++ b/app/webFrontend/src/app/user/user-details/user-details.component.html @@ -1,14 +1,14 @@ -

Profile

+
+

Profile

- + -

- -

+

+ +

- + +
\ No newline at end of file diff --git a/app/webFrontend/src/app/user/user-details/user-details.component.scss b/app/webFrontend/src/app/user/user-details/user-details.component.scss index e69de29bb..700cc4d60 100644 --- a/app/webFrontend/src/app/user/user-details/user-details.component.scss +++ b/app/webFrontend/src/app/user/user-details/user-details.component.scss @@ -0,0 +1,5 @@ +.user-detail-wrapper { + align-items: center; + display: flex; + flex-direction: column; +} \ No newline at end of file diff --git a/app/webFrontend/src/app/user/user-edit/user-edit.component.html b/app/webFrontend/src/app/user/user-edit/user-edit.component.html index 5d7d090dc..33ba98ec8 100644 --- a/app/webFrontend/src/app/user/user-edit/user-edit.component.html +++ b/app/webFrontend/src/app/user/user-edit/user-edit.component.html @@ -1,13 +1,45 @@ +

Edit profile

+
+ +
- + +
+ + {{'common.validation.required'|translate}} + + + common.validation.minLength + + + common.validation.maxLength + +
- + +
+ + {{'common.validation.required'|translate}} + + + common.validation.minLength + + + common.validation.maxLength + +
@@ -18,7 +50,7 @@

Edit profile

- +

-

+

-

+
+
diff --git a/app/webFrontend/src/app/user/user-edit/user-edit.component.scss b/app/webFrontend/src/app/user/user-edit/user-edit.component.scss index 9f197b816..9208ee70c 100644 --- a/app/webFrontend/src/app/user/user-edit/user-edit.component.scss +++ b/app/webFrontend/src/app/user/user-edit/user-edit.component.scss @@ -1,7 +1,30 @@ -.user-form { - width: 300px; +$viewWidth: 300px; - .full-width { - width: 100%; - } +.user-icon { + background-size: cover; + border-radius: 1.25rem; + display: inline-block; + height: 2.5rem; + margin-bottom: 20px; + vertical-align: middle; + width: 2.5rem; } + +.edit-user-wrapper { + align-items: center; + display: flex; + flex-direction: column; + + .user-form { + width: $viewWidth; + + .full-width { + width: 100%; + } + } + + .button-wrapper { + margin-top: 10px; + width: $viewWidth; + } +} \ No newline at end of file diff --git a/app/webFrontend/src/app/user/user-edit/user-edit.component.ts b/app/webFrontend/src/app/user/user-edit/user-edit.component.ts index a3ccb7445..0591c43d2 100644 --- a/app/webFrontend/src/app/user/user-edit/user-edit.component.ts +++ b/app/webFrontend/src/app/user/user-edit/user-edit.component.ts @@ -1,7 +1,8 @@ import {ChangeDetectorRef, Component, OnInit} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; import {FormGroup, FormBuilder, Validators} from '@angular/forms'; -import {MatSnackBar, MatDialog} from '@angular/material'; +import {MatDialog} from '@angular/material'; +import {SnackBarService} from '../../shared/services/snack-bar.service'; import {UserDataService} from '../../shared/services/data.service'; import {IUser} from '../../../../../../shared/models/IUser'; import {UserService} from '../../shared/services/user.service'; @@ -9,6 +10,7 @@ import {ShowProgressService} from '../../shared/services/show-progress.service'; import {DialogService} from '../../shared/services/dialog.service'; import {TitleService} from '../../shared/services/title.service'; import {ThemeService} from '../../shared/services/theme.service'; +import {emailValidator} from '../../shared/validators/validators'; @Component({ selector: 'app-user-edit', @@ -31,7 +33,7 @@ export class UserEditComponent implements OnInit { private showProgress: ShowProgressService, private formBuilder: FormBuilder, public dialogService: DialogService, - public snackBar: MatSnackBar, + public snackBar: SnackBarService, private titleService: TitleService, private cdRef: ChangeDetectorRef, private themeService: ThemeService) { @@ -70,15 +72,15 @@ export class UserEditComponent implements OnInit { email: this.user.email, }); this.titleService.setTitleCut(['Edit User: ', this.user.profile.firstName]); - } catch (error) { - this.snackBar.open(error.json().message, 'Dismiss'); + } catch (err) { + this.snackBar.open(err.error.message); } this.cdRef.detectChanges(); } async onSubmit() { - this.user = await this.prepareSaveUser(); - this.updateUser(); + this.user = this.prepareSaveUser(); + await this.updateUser(); } onCancel() { @@ -87,19 +89,15 @@ export class UserEditComponent implements OnInit { prepareSaveUser(): IUser { const userFormModel = this.userForm.value; - const saveUser: any = {}; - const saveIUser: IUser = saveUser; - for (const key in userFormModel) { - if (userFormModel.hasOwnProperty(key)) { - saveIUser[key] = userFormModel[key]; - } - } - for (const key in this.user) { - if (typeof saveIUser[key] === 'undefined') { - saveIUser[key] = this.user[key]; - } + + if (this.user.profile.picture) { + userFormModel.profile['picture'] = this.user.profile.picture; } + + const saveIUser: IUser = {...this.user, ...userFormModel}; + saveIUser['currentPassword'] = this.user.password; + return saveIUser; } @@ -107,15 +105,14 @@ export class UserEditComponent implements OnInit { this.showProgress.toggleLoadingGlobal(true); try { const user = await this.userDataService.updateItem(this.user); - this.snackBar.open('Profile successfully updated.', '', {duration: 3000}); + this.snackBar.open('Profile successfully updated.'); if (this.userService.isLoggedInUser(user)) { this.userService.setUser(user); } this.navigateBack(); - } catch (error) { - const errormsg = error.message; - this.snackBar.open(errormsg, 'Dismiss'); + } catch (err) { + this.snackBar.open(err.error.message); } this.showProgress.toggleLoadingGlobal(false); } @@ -123,12 +120,12 @@ export class UserEditComponent implements OnInit { generateForm() { this.userForm = this.formBuilder.group({ profile: this.formBuilder.group({ - firstName: ['', Validators.required], - lastName: ['', Validators.required], + firstName: ['', Validators.compose([Validators.required, Validators.minLength(2), Validators.maxLength(64)])], + lastName: ['', Validators.compose([Validators.required, Validators.minLength(2), Validators.maxLength(64)])], theme: [''], }), username: [''], - email: ['', Validators.required], + email: ['', emailValidator], currentPassword: [''] }); } @@ -140,17 +137,14 @@ export class UserEditComponent implements OnInit { } this.user.password = this.generatePass(12); this.showProgress.toggleLoadingGlobal(true); - const user = await this.userDataService.updateItem(this.user); try { - if (!user) { - throw new Error('an unknown error occured'); - } - await this.dialogService.info( + await this.userDataService.updateItem(this.user); + this.dialogService.info( 'Password successfully updated', - 'Password for user ' + this.user.email + ' was updated to: \'' + this.user.password + '\'').toPromise(); - this.snackBar.open('Password updated', '', {duration: 3000}); - } catch (error) { - this.snackBar.open(error.json().message, '', {duration: 3000}); + 'Password for user ' + this.user.email + ' was updated to: \'' + this.user.password + '\'' + ); + } catch (err) { + this.snackBar.open(err.error.message); } this.showProgress.toggleLoadingGlobal(false); } @@ -159,9 +153,10 @@ export class UserEditComponent implements OnInit { const response = await this.dialogService.upload(this.user).toPromise(); if (response && response.success && response.user) { if (this.userService.isLoggedInUser(response.user)) { + this.user = response.user; this.userService.setUser(response.user); } - this.snackBar.open('User image successfully uploaded.', '', {duration: 3000}); + this.updateUser(); } } diff --git a/app/webFrontend/src/app/user/user-profile/user-profile.component.html b/app/webFrontend/src/app/user/user-profile/user-profile.component.html index 7ec0779cd..7f2b3b35c 100644 --- a/app/webFrontend/src/app/user/user-profile/user-profile.component.html +++ b/app/webFrontend/src/app/user/user-profile/user-profile.component.html @@ -1,15 +1,15 @@
-

+

- {{user.profile.firstName}} {{user.profile.lastName}} + {{user.profile.firstName}} {{user.profile.lastName}} - {{user.profile.firstName}} {{user.profile.lastName}} + {{user.profile.firstName}} {{user.profile.lastName}}

- E-Mail:{{user.email}} + E-Mail: {{user.email}} - Matrikelnummer: {{user.uid}} + Matrikelnummer: {{user.uid}}
diff --git a/app/webFrontend/src/app/user/user-profile/user-profile.component.scss b/app/webFrontend/src/app/user/user-profile/user-profile.component.scss index 5760d3b61..25fe497c3 100644 --- a/app/webFrontend/src/app/user/user-profile/user-profile.component.scss +++ b/app/webFrontend/src/app/user/user-profile/user-profile.component.scss @@ -10,10 +10,33 @@ vertical-align: middle; } - .name { + .name-section { display: inline-block; vertical-align: middle; padding-left: 1rem; + + .name { + display: inline-block; + + @media screen and (max-width: 1275px) { + overflow: hidden; + max-width: 60rem; + text-overflow: ellipsis; + white-space: nowrap; + + @media screen and (max-width: 1070px) { + max-width: 40rem; + + @media screen and (max-width: 750px) { + max-width: 15rem; + + @media screen and (max-width: 350px) { + max-width: 10rem; + } + } + } + } + } } .user-data { diff --git a/app/webFrontend/src/app/user/user-profile/user-profile.component.ts b/app/webFrontend/src/app/user/user-profile/user-profile.component.ts index 817f33600..a6db00dec 100644 --- a/app/webFrontend/src/app/user/user-profile/user-profile.component.ts +++ b/app/webFrontend/src/app/user/user-profile/user-profile.component.ts @@ -1,6 +1,6 @@ import {Component, Input, OnInit} from '@angular/core'; import {UserService} from '../../shared/services/user.service'; -import {IFile} from '../../../../../../shared/models/mediaManager/IFile'; +import {IFile} from '../../../../../../shared/models/IFile'; import {User} from '../../models/User'; @Component({ diff --git a/app/webFrontend/src/app/user/user-report/user-report.component.scss b/app/webFrontend/src/app/user/user-report/user-report.component.scss index c639d8c51..d17285585 100644 --- a/app/webFrontend/src/app/user/user-report/user-report.component.scss +++ b/app/webFrontend/src/app/user/user-report/user-report.component.scss @@ -1,3 +1,34 @@ +$min-screen-size: 520px; +$small-box-size: 280px; +$large-box-size: 500px; + mat-card { margin-bottom: 1rem; + + &.ng-star-inserted { + max-width: 500px; + min-width: $small-box-size; + + @media screen and (max-width: $min-screen-size) { + max-width: $small-box-size; + } + } + + ngx-charts-advanced-pie-chart > div:first-child { + display: flex; + height: 100% !important; // !important to override the inline style of the ngx-charts-advanced-pie-chart component. Don't use it in other cases! + width: 100% !important; + + .advanced-pie-legend-wrapper, .advanced-pie-legend, .ngx-charts-outer { + width: 100% !important; + } + + .ngx-charts { + width: 200px; + } + + @media screen and (max-width: $min-screen-size) { + flex-direction: column; + } + } } diff --git a/app/webFrontend/src/app/user/user-settings/user-settings.component.ts b/app/webFrontend/src/app/user/user-settings/user-settings.component.ts index 5698399bb..dca107698 100644 --- a/app/webFrontend/src/app/user/user-settings/user-settings.component.ts +++ b/app/webFrontend/src/app/user/user-settings/user-settings.component.ts @@ -10,13 +10,14 @@ import { } from '../../../../../../shared/models/INotificationSettings'; import {NotificationSettings} from '../../models/NotificationSettings'; import {isNullOrUndefined} from 'util'; +import {AfterContentInit} from '@angular/core/src/metadata/lifecycle_hooks'; @Component({ selector: 'app-user-settings', templateUrl: './user-settings.component.html', styleUrls: ['./user-settings.component.scss'] }) -export class UserSettingsComponent implements OnInit { +export class UserSettingsComponent implements OnInit, AfterContentInit { myCourses: ICourse[]; displayedColumns = ['name', 'Notifications', 'email']; @@ -37,6 +38,10 @@ export class UserSettingsComponent implements OnInit { this.setSelection(); }); } + async ngAfterContentInit() { + await this.getNotificationSettings(); + this.setSelection(); + } getCourses() { this.myCourses = []; @@ -47,7 +52,7 @@ export class UserSettingsComponent implements OnInit { } }); this.dataSource = new MatTableDataSource(this.myCourses); - }) + }); } async getNotificationSettings() { @@ -56,7 +61,7 @@ export class UserSettingsComponent implements OnInit { await Promise.all(this.myCourses.map(async (course) => { const newSetting = await this.notificationSettingsService.createItem({user: this.userService.user, course: course}); settings.push(newSetting); - })) + })); } this.notificationSettings = settings; } diff --git a/app/webFrontend/src/assets/i18n/de.json b/app/webFrontend/src/assets/i18n/de.json index 432cb4681..ca0d1e594 100644 --- a/app/webFrontend/src/assets/i18n/de.json +++ b/app/webFrontend/src/assets/i18n/de.json @@ -5,6 +5,7 @@ "register": "Registrieren", "email": "E-Mail", "password": "Passwort", + "send": "Senden", "dismiss": "Schließen", "back": "Zurück", "profile": { @@ -19,6 +20,7 @@ "validation": { "required": "Eingabe notwendig", "minLength": "Mindestens {{min}} Zeichen benötigt", + "maxLength": "Maximal {{max}} Zeichen erlaubt", "invalid": "Keine gültige Eingabe", "password": "Passwörter müssen aus mindestens 8 Zeichen, inklusive einem Sonderzeichen und einer Ziffer bestehen", "passwordsMatch": "Die Passwörter stimmen nicht überein", @@ -43,7 +45,13 @@ "successful": "Registrierung erfolgreich", "mailSent": "Wir haben Ihnen einen Aktivierungslink an Ihre E-Mail-Adresse gesendet.", "back": "Zurück zur Startseite", - "teacherRegistrationButton": "Kein Student?" + "teacherRegistrationButton": "Kein Student?", + "resendActivationButton": "Aktivierung erneut senden" + }, + "resendActivation": { + "back": "Zurück zur Registrierung", + "successful": "Aktivierung erneut senden erfolgreich", + "mailSent": "Wir haben Ihnen einen neuen Aktivierungslink an Ihre E-Mail-Adresse gesendet." } }, "mainMenu": { diff --git a/app/webFrontend/src/assets/i18n/en.json b/app/webFrontend/src/assets/i18n/en.json index a05ff99f8..87dbd30e1 100644 --- a/app/webFrontend/src/assets/i18n/en.json +++ b/app/webFrontend/src/assets/i18n/en.json @@ -5,6 +5,7 @@ "register": "Register", "email": "Email", "password": "Password", + "send": "Send", "dismiss": "Dismiss", "back": "Back", "profile": { @@ -19,6 +20,7 @@ "validation": { "required": "Input required", "minLength": "At least {{min}} characters required", + "maxLength": "At least {{max}} characters required", "invalid": "Input is invalid", "password": "Password must have at least 8 characters which contain one special character or digit", "passwordsMatch": "Passwords do not match", @@ -41,9 +43,15 @@ "registration": { "registerAs": "Register as", "successful": "Registration was successful", - "mailSent": "We have send you an activation link to your specified email address.", + "mailSent": "We have sent you an activation link to your specified email address.", "back": "Back to frontpage", - "teacherRegistrationButton": "Not a student?" + "teacherRegistrationButton": "Not a student?", + "resendActivationButton": "Resend activation" + }, + "resendActivation": { + "back": "Back to registration", + "successful": "Resend activation was successful", + "mailSent": "We have sent you a new activation link to your specified email address." } }, "mainMenu": { diff --git a/app/webFrontend/src/tsconfig.spec.json b/app/webFrontend/src/tsconfig.spec.json index 0967ef424..f5ab4f699 100644 --- a/app/webFrontend/src/tsconfig.spec.json +++ b/app/webFrontend/src/tsconfig.spec.json @@ -1 +1,19 @@ -{} +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "baseUrl": "./", + "module": "es6", + "outDir": "../out-tsc/spec", + "types": [ + "jasmine", + "node" + ] + }, + "files": [ + "test.ts" + ], + "include": [ + "**/*.spec.ts", + "**/*.d.ts" + ] +} diff --git a/docker-compose.yml b/docker-compose.yml index c417af27d..724b673c8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,7 +5,7 @@ services: ports: - "27017:27017" api: - image: "node:8.9.0" + image: "node:8.11.1" volumes: - ".:/usr/src" working_dir: "/usr/src/api" @@ -17,7 +17,7 @@ services: links: - "db" web-frontend: - image: "node:8.9.0" + image: "node:8.11.1" volumes: - ".:/usr/src" working_dir: "/usr/src/app/webFrontend" diff --git a/docs/development/running-locally.md b/docs/development/running-locally.md index bb95a7499..4eb662320 100644 --- a/docs/development/running-locally.md +++ b/docs/development/running-locally.md @@ -5,7 +5,7 @@ and [MongoDB](https://docs.mongodb.com/manual/installation/) on your machine. ⚠️ **It is important to only use versions of Node.js and MongoDB that are currently supported by the project. You can find out which versions are currently supported by -looking at the [docker-compose.yml](docker-compose.yml) file.** ⚠️ +looking at the [docker-compose.yml](../../docker-compose.yml) file.** ⚠️ For running multiple versions of Node.js [nvm](https://github.com/creationix/nvm) is a very good option. diff --git a/shared/models/ICourse.ts b/shared/models/ICourse.ts index 24b6e699c..aa74a391e 100644 --- a/shared/models/ICourse.ts +++ b/shared/models/ICourse.ts @@ -9,17 +9,17 @@ export const ENROLL_TYPE_ACCESSKEY = 'accesskey'; export const ENROLL_TYPES = [ENROLL_TYPE_WHITELIST, ENROLL_TYPE_FREE, ENROLL_TYPE_ACCESSKEY]; export interface ICourse { - _id: any; - name: string; - active: boolean; - description: string; - courseAdmin: IUser; - media: IDirectory; - teachers: IUser[]; - students: IUser[]; - lectures: ILecture[]; - accessKey: string; - whitelist: IWhitelistUser[]; - enrollType: string; - hasAccessKey: boolean; + _id: any; + name: string; + active: boolean; + description: string; + courseAdmin: IUser; + media: IDirectory; + teachers: IUser[]; + students: IUser[]; + lectures: ILecture[]; + accessKey: string; + whitelist: IWhitelistUser[]; + enrollType: string; + hasAccessKey: boolean; } diff --git a/shared/models/ICourseDashboard.ts b/shared/models/ICourseDashboard.ts new file mode 100644 index 000000000..35f7b75ab --- /dev/null +++ b/shared/models/ICourseDashboard.ts @@ -0,0 +1,20 @@ +export {ENROLL_TYPE_WHITELIST} from './ICourse'; +export {ENROLL_TYPE_FREE} from './ICourse'; +export {ENROLL_TYPE_ACCESSKEY} from './ICourse'; +export {ENROLL_TYPES} from './ICourse'; + +export interface ICourseDashboard { + // As in ICourse: + _id: any; + name: string; + active: boolean; + description: string; + enrollType: string; + + // Special properties for the dashboard: + userCanEditCourse: boolean; + userCanViewCourse: boolean; + userIsCourseAdmin: boolean; + userIsCourseTeacher: boolean; + userIsCourseMember: boolean; +} diff --git a/shared/models/ICourseView.ts b/shared/models/ICourseView.ts new file mode 100644 index 000000000..660b502f5 --- /dev/null +++ b/shared/models/ICourseView.ts @@ -0,0 +1,11 @@ +import {ILecture} from './ILecture'; +import {IUserSubCourseView} from './IUserSubCourseView'; + +export interface ICourseView { + _id: any; + name: string; + description: string; + courseAdmin: IUserSubCourseView; + teachers: IUserSubCourseView[]; + lectures: ILecture[]; +} diff --git a/shared/models/IDownload.ts b/shared/models/IDownload.ts index ee12eeeeb..440fb5417 100644 --- a/shared/models/IDownload.ts +++ b/shared/models/IDownload.ts @@ -6,5 +6,5 @@ export interface IDownload { unitId: string; files?: Array }] - }] + }]; } diff --git a/shared/models/IFile.ts b/shared/models/IFile.ts index 1000ec634..3f7d67542 100644 --- a/shared/models/IFile.ts +++ b/shared/models/IFile.ts @@ -3,7 +3,7 @@ * This comes in with the use of the MediaManger. */ export interface IFile { - _id?: any, + _id?: any; path: string; name: string; alias: string; diff --git a/shared/models/IProperties.ts b/shared/models/IProperties.ts new file mode 100644 index 000000000..7fa86a7a2 --- /dev/null +++ b/shared/models/IProperties.ts @@ -0,0 +1,3 @@ +export interface IProperties { + [property: string]: any; +} diff --git a/shared/models/IUser.ts b/shared/models/IUser.ts index b024615da..dbc04e0fc 100644 --- a/shared/models/IUser.ts +++ b/shared/models/IUser.ts @@ -1,4 +1,4 @@ -import {IFile} from './mediaManager/IFile'; +import {IFile} from './IFile'; export interface IUser { _id: any; uid: string; diff --git a/shared/models/IUserSubCourseView.ts b/shared/models/IUserSubCourseView.ts new file mode 100644 index 000000000..f4ae692a0 --- /dev/null +++ b/shared/models/IUserSubCourseView.ts @@ -0,0 +1,9 @@ +import {IUserSubSafe} from './IUserSubSafe'; + +/** + * Subset of IUser for use in ICourseView. + * Superset of IUserSubSafe. + */ +export interface IUserSubCourseView extends IUserSubSafe { + email: string; +} diff --git a/shared/models/IUserSubSafe.ts b/shared/models/IUserSubSafe.ts new file mode 100644 index 000000000..4a92e55ed --- /dev/null +++ b/shared/models/IUserSubSafe.ts @@ -0,0 +1,13 @@ +import {IFile} from './IFile'; + +/** + * Safe subset of IUser that any logged-in user may see. + */ +export interface IUserSubSafe { + _id: any; + profile: { + firstName: string, + lastName: string; + picture?: IFile; + }; +} diff --git a/shared/models/IUserSubTeacher.ts b/shared/models/IUserSubTeacher.ts new file mode 100644 index 000000000..6670ef263 --- /dev/null +++ b/shared/models/IUserSubTeacher.ts @@ -0,0 +1,10 @@ +import {IUserSubSafe} from './IUserSubSafe'; + +/** + * Subset of IUser that any logged-in teacher (or equivalent) may see. + * Superset of IUserSubSafe. + */ +export interface IUserSubTeacher extends IUserSubSafe { + uid: string; + email: string; +} diff --git a/shared/models/IWhitelistUser.ts b/shared/models/IWhitelistUser.ts index c1a2e8190..f9dd2ead9 100644 --- a/shared/models/IWhitelistUser.ts +++ b/shared/models/IWhitelistUser.ts @@ -3,5 +3,5 @@ export interface IWhitelistUser { firstName: string; lastName: string; uid: string; - courseId: string + courseId: string; } diff --git a/shared/models/units/IUnit.ts b/shared/models/units/IUnit.ts index 4338517af..e0159a610 100644 --- a/shared/models/units/IUnit.ts +++ b/shared/models/units/IUnit.ts @@ -1,3 +1,5 @@ +import {IUser} from '../IUser'; + export interface IUnit { _id: any; _course: any; @@ -9,5 +11,7 @@ export interface IUnit { weight: number; updatedAt: string; createdAt: string; + unitCreator: IUser; + visible: boolean; __t: string; } diff --git a/tslint.json b/tslint.json index 3dd6749b5..b5ad9c4c5 100644 --- a/tslint.json +++ b/tslint.json @@ -9,7 +9,10 @@ "curly": true, "eofline": true, "forin": true, - "import-blacklist": [true, "rxjs"], + "import-blacklist": [ + true, + "rxjs" + ], "import-spacing": true, "indent": [ true, @@ -43,9 +46,11 @@ "no-debugger": true, "no-duplicate-variable": true, "no-empty": false, - // "no-empty-interface": true, // Problematic for interface combining multiple interfaces "no-eval": true, - "no-inferrable-types": [true, "ignore-params"], + "no-inferrable-types": [ + true, + "ignore-params" + ], "no-shadowed-variable": true, "no-string-literal": false, "no-string-throw": true, @@ -69,6 +74,7 @@ ], "radix": true, "semicolon": [ + true, "always" ], "triple-equals": [ @@ -85,7 +91,6 @@ "variable-declaration": "nospace" } ], - "typeof-compare": true, "unified-signatures": true, "variable-name": false, "whitespace": [