From 8fd7dbf13340f02b2f82e09292cd37c34dec3917 Mon Sep 17 00:00:00 2001 From: Simon Detheridge Date: Sun, 16 Feb 2020 13:59:59 +0000 Subject: [PATCH 01/27] decaffeinate: update build scripts to es --- services/docstore/.dockerignore | 2 - services/docstore/.eslintrc | 65 +++++++++++++++++++++++++++++++ services/docstore/.prettierrc | 8 ++++ services/docstore/Dockerfile | 1 - services/docstore/Jenkinsfile | 7 ++++ services/docstore/Makefile | 15 ++++--- services/docstore/buildscript.txt | 14 +++---- services/docstore/nodemon.json | 7 ++-- services/docstore/package.json | 18 ++++----- 9 files changed, 108 insertions(+), 29 deletions(-) create mode 100644 services/docstore/.eslintrc create mode 100644 services/docstore/.prettierrc diff --git a/services/docstore/.dockerignore b/services/docstore/.dockerignore index 386f26df30..ba1c3442de 100644 --- a/services/docstore/.dockerignore +++ b/services/docstore/.dockerignore @@ -5,5 +5,3 @@ gitrev .npm .nvmrc nodemon.json -app.js -**/js/* diff --git a/services/docstore/.eslintrc b/services/docstore/.eslintrc new file mode 100644 index 0000000000..42a4b5cace --- /dev/null +++ b/services/docstore/.eslintrc @@ -0,0 +1,65 @@ +// this file was auto-generated, do not edit it directly. +// instead run bin/update_build_scripts from +// https://github.com/sharelatex/sharelatex-dev-environment +// Version: 1.3.5 +{ + "extends": [ + "standard", + "prettier", + "prettier/standard" + ], + "parserOptions": { + "ecmaVersion": 2017 + }, + "plugins": [ + "mocha", + "chai-expect", + "chai-friendly" + ], + "env": { + "node": true, + "mocha": true + }, + "rules": { + // Swap the no-unused-expressions rule with a more chai-friendly one + "no-unused-expressions": 0, + "chai-friendly/no-unused-expressions": "error" + }, + "overrides": [ + { + // Test specific rules + "files": ["test/**/*.js"], + "globals": { + "expect": true + }, + "rules": { + // mocha-specific rules + "mocha/handle-done-callback": "error", + "mocha/no-exclusive-tests": "error", + "mocha/no-global-tests": "error", + "mocha/no-identical-title": "error", + "mocha/no-nested-tests": "error", + "mocha/no-pending-tests": "error", + "mocha/no-skipped-tests": "error", + "mocha/no-mocha-arrows": "error", + + // chai-specific rules + "chai-expect/missing-assertion": "error", + "chai-expect/terminating-properties": "error", + + // prefer-arrow-callback applies to all callbacks, not just ones in mocha tests. + // we don't enforce this at the top-level - just in tests to manage `this` scope + // based on mocha's context mechanism + "mocha/prefer-arrow-callback": "error" + } + }, + { + // Backend specific rules + "files": ["app/**/*.js", "app.js", "index.js"], + "rules": { + // don't allow console.log in backend code + "no-console": "error" + } + } + ] +} diff --git a/services/docstore/.prettierrc b/services/docstore/.prettierrc new file mode 100644 index 0000000000..5845b82113 --- /dev/null +++ b/services/docstore/.prettierrc @@ -0,0 +1,8 @@ +# This file was auto-generated, do not edit it directly. +# Instead run bin/update_build_scripts from +# https://github.com/sharelatex/sharelatex-dev-environment +# Version: 1.3.5 +{ + "semi": false, + "singleQuote": true +} diff --git a/services/docstore/Dockerfile b/services/docstore/Dockerfile index e538fb48d9..2d8b097e26 100644 --- a/services/docstore/Dockerfile +++ b/services/docstore/Dockerfile @@ -17,7 +17,6 @@ RUN npm install --quiet COPY . /app -RUN npm run compile:all FROM base diff --git a/services/docstore/Jenkinsfile b/services/docstore/Jenkinsfile index 14ea3db943..95132d21db 100644 --- a/services/docstore/Jenkinsfile +++ b/services/docstore/Jenkinsfile @@ -37,6 +37,13 @@ pipeline { } } + stage('Linting') { + steps { + sh 'DOCKER_COMPOSE_FLAGS="-f docker-compose.ci.yml" make format' + sh 'DOCKER_COMPOSE_FLAGS="-f docker-compose.ci.yml" make lint' + } + } + stage('Unit Tests') { steps { sh 'DOCKER_COMPOSE_FLAGS="-f docker-compose.ci.yml" make test_unit' diff --git a/services/docstore/Makefile b/services/docstore/Makefile index d720f78b65..1314c0d76d 100644 --- a/services/docstore/Makefile +++ b/services/docstore/Makefile @@ -19,12 +19,17 @@ DOCKER_COMPOSE := BUILD_NUMBER=$(BUILD_NUMBER) \ clean: docker rmi ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) docker rmi gcr.io/overleaf-ops/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) - rm -f app.js - rm -rf app/js - rm -rf test/unit/js - rm -rf test/acceptance/js -test: test_unit test_acceptance +format: + $(DOCKER_COMPOSE) run --rm test_unit npm run format + +format_fix: + $(DOCKER_COMPOSE) run --rm test_unit npm run format:fix + +lint: + $(DOCKER_COMPOSE) run --rm test_unit npm run lint + +test: format lint test_unit test_acceptance test_unit: @[ ! -d test/unit ] && echo "docstore has no unit tests" || $(DOCKER_COMPOSE) run --rm test_unit diff --git a/services/docstore/buildscript.txt b/services/docstore/buildscript.txt index 8c8706f1cf..77a5b00f8c 100644 --- a/services/docstore/buildscript.txt +++ b/services/docstore/buildscript.txt @@ -1,10 +1,10 @@ docstore ---public-repo=True ---language=coffeescript ---env-add= --node-version=10.19.0 ---acceptance-creds=aws ---dependencies=mongo ---docker-repos=gcr.io/overleaf-ops ---env-pass-through= --script-version=1.3.5 +--dependencies=mongo +--language=es +--docker-repos=gcr.io/overleaf-ops +--acceptance-creds=aws +--env-pass-through= +--env-add= +--public-repo=True diff --git a/services/docstore/nodemon.json b/services/docstore/nodemon.json index 98db38d71b..5826281b84 100644 --- a/services/docstore/nodemon.json +++ b/services/docstore/nodemon.json @@ -10,10 +10,9 @@ }, "watch": [ - "app/coffee/", - "app.coffee", + "app/js/", + "app.js", "config/" ], - "ext": "coffee" - + "ext": "js" } diff --git a/services/docstore/package.json b/services/docstore/package.json index b0b24ce551..ff0950cf27 100644 --- a/services/docstore/package.json +++ b/services/docstore/package.json @@ -8,17 +8,15 @@ "url": "https://github.com/sharelatex/docstore-sharelatex.git" }, "scripts": { - "compile:app": "([ -e app/coffee ] && coffee -m $COFFEE_OPTIONS -o app/js -c app/coffee || echo 'No CoffeeScript folder to compile') && ( [ -e app.coffee ] && coffee -m $COFFEE_OPTIONS -c app.coffee || echo 'No CoffeeScript app to compile')", - "start": "npm run compile:app && node $NODE_APP_OPTIONS app.js", - "test:acceptance:_run": "AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY AWS_BUCKET=$AWS_BUCKET AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID mocha --recursive --reporter spec --timeout 30000 --exit $@ test/acceptance/js", - "test:acceptance": "npm run compile:app && npm run compile:acceptance_tests && npm run test:acceptance:_run -- --grep=$MOCHA_GREP", - "test:unit:_run": "mocha --recursive --reporter spec --exit $@ test/unit/js", - "test:unit": "npm run compile:app && npm run compile:unit_tests && npm run test:unit:_run -- --grep=$MOCHA_GREP", - "compile:unit_tests": "[ ! -e test/unit/coffee ] && echo 'No unit tests to compile' || coffee -o test/unit/js -c test/unit/coffee", - "compile:acceptance_tests": "[ ! -e test/acceptance/coffee ] && echo 'No acceptance tests to compile' || coffee -o test/acceptance/js -c test/acceptance/coffee", - "compile:all": "npm run compile:app && npm run compile:unit_tests && npm run compile:acceptance_tests && npm run compile:smoke_tests", + "start": "node $NODE_APP_OPTIONS app.js", + "test:acceptance:_run": "mocha --recursive --reporter spec --timeout 15000 --exit $@ test/acceptance/js", + "test:acceptance": "npm run test:acceptance:_run -- --grep=$MOCHA_GREP", + "test:unit:_run": "mocha --recursive --reporter spec $@ test/unit/js", + "test:unit": "npm run test:unit:_run -- --grep=$MOCHA_GREP", "nodemon": "nodemon --config nodemon.json", - "compile:smoke_tests": "[ ! -e test/smoke/coffee ] && echo 'No smoke tests to compile' || coffee -o test/smoke/js -c test/smoke/coffee" + "lint": "node_modules/.bin/eslint .", + "format": "node_modules/.bin/prettier-eslint '**/*.js' --list-different", + "format:fix": "node_modules/.bin/prettier-eslint '**/*.js' --write" }, "dependencies": { "async": "~0.8.0", From b54e4cd2762805585c7ab595a138a2fb2c37381d Mon Sep 17 00:00:00 2001 From: Simon Detheridge Date: Sun, 16 Feb 2020 14:00:36 +0000 Subject: [PATCH 02/27] decaffeinate: update .gitignore --- services/docstore/.gitignore | 5 ----- 1 file changed, 5 deletions(-) diff --git a/services/docstore/.gitignore b/services/docstore/.gitignore index 6a355b35a8..50678c09e9 100644 --- a/services/docstore/.gitignore +++ b/services/docstore/.gitignore @@ -1,7 +1,2 @@ node_modules -app/js/ -test/unit/js -test/acceptance/js -app.js -**/*.map forever From b4aec5394b8fce84bff0b888458a34a52093fd69 Mon Sep 17 00:00:00 2001 From: Simon Detheridge Date: Sun, 16 Feb 2020 14:01:32 +0000 Subject: [PATCH 03/27] decaffeinate: add eslint and prettier packages --- services/docstore/package-lock.json | 3029 ++++++++++++++++++++++++++- services/docstore/package.json | 18 + 2 files changed, 3044 insertions(+), 3 deletions(-) diff --git a/services/docstore/package-lock.json b/services/docstore/package-lock.json index 9eab5b1bd3..3ed5f34f56 100644 --- a/services/docstore/package-lock.json +++ b/services/docstore/package-lock.json @@ -4,6 +4,146 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/generator": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz", + "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helper-function-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", + "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", + "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", + "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", + "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==", + "dev": true + }, + "@babel/runtime": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.4.tgz", + "integrity": "sha512-neAp3zt80trRVBI1x0azq6c57aNBqYZH8KhMm3TaB7wEI5Q4A2SHfBHE8w9gOhI/lrqxtEbXZgQIrHP+wvSGwQ==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.2" + } + }, + "@babel/template": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", + "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/traverse": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz", + "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.4", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/parser": "^7.8.4", + "@babel/types": "^7.8.3", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, "@google-cloud/common": { "version": "0.32.1", "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-0.32.1.tgz", @@ -284,6 +424,12 @@ "@types/node": "*" } }, + "@types/eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", + "dev": true + }, "@types/form-data": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz", @@ -292,6 +438,12 @@ "@types/node": "*" } }, + "@types/json-schema": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz", + "integrity": "sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==", + "dev": true + }, "@types/long": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.0.tgz", @@ -323,6 +475,51 @@ "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.5.tgz", "integrity": "sha512-SCcK7mvGi3+ZNz833RRjFIxrn4gI1PPR3NtuIS+6vMkvmsGjosqTJwRt5bAEFLRz+wtJMWv8+uOnZf2hi2QXTg==" }, + "@typescript-eslint/experimental-utils": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-1.13.0.tgz", + "integrity": "sha512-zmpS6SyqG4ZF64ffaJ6uah6tWWWgZ8m+c54XXgwFtUv0jNz8aJAVx8chMCvnk7yl6xwn8d+d96+tWp7fXzTuDg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/typescript-estree": "1.13.0", + "eslint-scope": "^4.0.0" + }, + "dependencies": { + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-1.13.0.tgz", + "integrity": "sha512-ITMBs52PCPgLb2nGPoeT4iU3HdQZHcPaZVw+7CsFagRJHUhyeTgorEwHXhFf3e7Evzi8oujKNpHc8TONth8AdQ==", + "dev": true, + "requires": { + "@types/eslint-visitor-keys": "^1.0.0", + "@typescript-eslint/experimental-utils": "1.13.0", + "@typescript-eslint/typescript-estree": "1.13.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "@typescript-eslint/typescript-estree": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.13.0.tgz", + "integrity": "sha512-b5rCmd2e6DCC6tCTN9GSUAuxdYwCM/k/2wdjHGrIRGPSJotWMCe/dGpi66u42bhuh8q3QBzqM4TMA1GUUCJvdw==", + "dev": true, + "requires": { + "lodash.unescape": "4.0.1", + "semver": "5.5.0" + } + }, "abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -345,6 +542,12 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==" }, + "acorn-jsx": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", + "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", + "dev": true + }, "agent-base": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", @@ -364,6 +567,70 @@ "uri-js": "^4.2.2" } }, + "ansi-escapes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.0.tgz", + "integrity": "sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "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.0" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "aria-query": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz", + "integrity": "sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=", + "dev": true, + "requires": { + "ast-types-flow": "0.0.7", + "commander": "^2.11.0" + } + }, + "array-includes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", + "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "is-string": "^1.0.5" + } + }, + "array.prototype.flat": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", + "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, "arrify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", @@ -389,6 +656,18 @@ "integrity": "sha1-x/hUOP3UZrx8oWq5DIFRN5el0js=", "dev": true }, + "ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", + "dev": true + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, "async": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/async/-/async-0.8.0.tgz", @@ -429,6 +708,37 @@ "is-buffer": "^2.0.2" } }, + "axobject-query": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.1.2.tgz", + "integrity": "sha512-ICt34ZmrVt8UQnvPl6TVyDTkmhXmAyAT4Jh5ugfGUX4MOrZ+U/ZY6/sdylRw3qGNr9Ub5AJsaHeDMzNLehRdOQ==", + "dev": true + }, + "babel-eslint": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.0.3.tgz", + "integrity": "sha512-z3U7eMY6r/3f3/JB9mTsLjyxrv0Yb1zb8PCWCLpguxfCzBIZUwy23R1t/XKewP+8mEN2Ck8Dtr4q20z6ce6SoA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", + "eslint-visitor-keys": "^1.0.0", + "resolve": "^1.12.0" + }, + "dependencies": { + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -475,12 +785,17 @@ "type-is": "~1.1.0" } }, + "boolify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/boolify/-/boolify-1.0.1.tgz", + "integrity": "sha1-tcCeF8rNET0Rt7s+04TMASmU2Gs=", + "dev": true + }, "boom": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", "integrity": "sha1-emNune1O/O+xnO9JR6PGffrukRs=", "dev": true, - "optional": true, "requires": { "hoek": "0.9.x" } @@ -540,6 +855,29 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=" }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "camelcase-keys": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.1.2.tgz", + "integrity": "sha512-QfFrU0CIw2oltVvpndW32kuJ/9YOJwUnmWrjlXt1nnJZHCaS9i6bfOpg9R4Lw8aZjStkJWM+jc0cdXjWBgVJSw==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + } + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -555,11 +893,111 @@ "deep-eql": "0.1.3" } }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "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.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + } + } + }, "coffee-script": { "version": "1.12.7", "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==" }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, "combined-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", @@ -570,6 +1008,18 @@ "delayed-stream": "0.0.5" } }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "common-tags": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", + "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==", + "dev": true + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -580,6 +1030,12 @@ "resolved": "https://registry.npmjs.org/console-log-level/-/console-log-level-1.4.1.tgz", "integrity": "sha512-VZzbIORbP+PPcN/gg3DXClTLPLg5Slwd5fL2MIc+o1qZ4BXBvWyc6QxPk6T/Mkr6IVjRpoAGf32XxP3ZWMVRcQ==" }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, "continuation-local-storage": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/continuation-local-storage/-/continuation-local-storage-3.2.1.tgz", @@ -599,11 +1055,30 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.3.tgz", "integrity": "sha1-kc2ZfMUftkFZVzjGnNoCAyj1D/k=" }, + "core-js": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.4.tgz", + "integrity": "sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==", + "dev": true + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, "cryptiles": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", @@ -621,6 +1096,12 @@ "dev": true, "optional": true }, + "damerau-levenshtein": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz", + "integrity": "sha512-JVrozIeElnj3QzfUIt8tB8YMluBJom4Vw9qTPpjGYQ9fYlB3D/rb6OordUxf3xeFB35LKWs0xqcO5U6ySvBtug==", + "dev": true + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -641,6 +1122,12 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-0.8.1.tgz", "integrity": "sha1-IP9NJvXkIstoobrLu2EDmtjBwTA=" }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, "deep-eql": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", @@ -650,6 +1137,21 @@ "type-detect": "0.1.1" } }, + "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 + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, "delay": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/delay/-/delay-4.3.0.tgz", @@ -662,6 +1164,21 @@ "dev": true, "optional": true }, + "dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, "dtrace-provider": { "version": "0.2.8", "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.2.8.tgz", @@ -710,6 +1227,12 @@ "shimmer": "^1.2.0" } }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", @@ -723,6 +1246,45 @@ "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=" }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", + "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, "es6-promise": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz", @@ -754,6 +1316,454 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, + "eslint": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.6.0.tgz", + "integrity": "sha512-PpEBq7b6qY/qrOmpYQ/jTMDYfuQMELR4g4WI1M/NaSDDD/bdcMb+dj4Hgks7p41kW2caXsPsEZAEAyAgjVVC0g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.4.3", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.2", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^7.0.0", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "eslint-config-prettier": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.10.0.tgz", + "integrity": "sha512-AtndijGte1rPILInUdHjvKEGbIV06NuvPrqlIEaEaWtbtvJh464mDeyGMdZEQMsGvC0ZVkiex1fSNcC4HAbRGg==", + "dev": true, + "requires": { + "get-stdin": "^6.0.0" + } + }, + "eslint-config-standard": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-14.1.0.tgz", + "integrity": "sha512-EF6XkrrGVbvv8hL/kYa/m6vnvmUT+K82pJJc4JJVMM6+Qgqh0pnwprSxdduDLB9p/7bIxD+YV5O0wfb8lmcPbA==", + "dev": true + }, + "eslint-config-standard-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-8.1.0.tgz", + "integrity": "sha512-ULVC8qH8qCqbU792ZOO6DaiaZyHNS/5CZt3hKqHkEhVlhPEPN3nfBqqxJCyp59XrjIBZPu1chMYe9T2DXZ7TMw==", + "dev": true + }, + "eslint-config-standard-react": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard-react/-/eslint-config-standard-react-9.2.0.tgz", + "integrity": "sha512-u+KRP2uCtthZ/W4DlLWCC59GZNV/y9k9yicWWammgTs/Omh8ZUUPF3EnYm81MAcbkYQq2Wg0oxutAhi/FQ8mIw==", + "dev": true, + "requires": { + "eslint-config-standard-jsx": "^8.0.0" + } + }, + "eslint-import-resolver-node": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz", + "integrity": "sha512-b8crLDo0M5RSe5YG8Pu2DYBj71tSB6OvXkfzwbJU2w7y8P4/yo0MyF8jU26IEuEuHF2K5/gcAJE3LhQGqBBbVg==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.13.1" + }, + "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" + } + }, + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "eslint-module-utils": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.5.2.tgz", + "integrity": "sha512-LGScZ/JSlqGKiT8OC+cYRxseMjyqt6QO54nl281CK93unD89ijSeRV6An8Ci/2nvWVKe8K/Tqdm75RQoIOCr+Q==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "pkg-dir": "^2.0.0" + }, + "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" + } + } + } + }, + "eslint-plugin-chai-expect": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-chai-expect/-/eslint-plugin-chai-expect-2.1.0.tgz", + "integrity": "sha512-rd0/4mjMV6c3i0o4DKkWI4uaFN9DK707kW+/fDphaDI6HVgxXnhML9Xgt5vHnTXmSSnDhupuCFBgsEAEpchXmQ==", + "dev": true + }, + "eslint-plugin-chai-friendly": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-chai-friendly/-/eslint-plugin-chai-friendly-0.5.0.tgz", + "integrity": "sha512-Pxe6z8C9fP0pn2X2nGFU/b3GBOCM/5FVus1hsMwJsXP3R7RiXFl7g0ksJbsc0GxiLyidTW4mEFk77qsNn7Tk7g==", + "dev": true + }, + "eslint-plugin-es": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.0.tgz", + "integrity": "sha512-6/Jb/J/ZvSebydwbBJO1R9E5ky7YeElfK56Veh7e4QGFHCXoIXGH9HhVz+ibJLM3XJ1XjP+T7rKBLUa/Y7eIng==", + "dev": true, + "requires": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + }, + "dependencies": { + "eslint-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz", + "integrity": "sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "regexpp": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.0.0.tgz", + "integrity": "sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g==", + "dev": true + } + } + }, + "eslint-plugin-import": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.20.1.tgz", + "integrity": "sha512-qQHgFOTjguR+LnYRoToeZWT62XM55MBVXObHM6SKFd1VzDcX/vqT1kAz8ssqigh5eMj8qXcRoXXGZpPP6RfdCw==", + "dev": true, + "requires": { + "array-includes": "^3.0.3", + "array.prototype.flat": "^1.2.1", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.2", + "eslint-module-utils": "^2.4.1", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.0", + "read-pkg-up": "^2.0.0", + "resolve": "^1.12.0" + }, + "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" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "eslint-plugin-jsx-a11y": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.2.3.tgz", + "integrity": "sha512-CawzfGt9w83tyuVekn0GDPU9ytYtxyxyFZ3aSWROmnRRFQFT2BiPJd7jvRdzNDi6oLWaS2asMeYSNMjWTV4eNg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.4.5", + "aria-query": "^3.0.0", + "array-includes": "^3.0.3", + "ast-types-flow": "^0.0.7", + "axobject-query": "^2.0.2", + "damerau-levenshtein": "^1.0.4", + "emoji-regex": "^7.0.2", + "has": "^1.0.3", + "jsx-ast-utils": "^2.2.1" + }, + "dependencies": { + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + } + } + }, + "eslint-plugin-mocha": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-6.2.2.tgz", + "integrity": "sha512-oNhPzfkT6Q6CJ0HMVJ2KLxEWG97VWGTmuHOoRcDLE0U88ugUyFNV9wrT2XIt5cGtqc5W9k38m4xTN34L09KhBA==", + "dev": true, + "requires": { + "ramda": "^0.26.1" + } + }, + "eslint-plugin-node": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.0.0.tgz", + "integrity": "sha512-chUs/NVID+sknFiJzxoN9lM7uKSOEta8GC8365hw1nDfwIPIjjpRSwwPvQanWv8dt/pDe9EV4anmVSwdiSndNg==", + "dev": true, + "requires": { + "eslint-plugin-es": "^3.0.0", + "eslint-utils": "^2.0.0", + "ignore": "^5.1.1", + "minimatch": "^3.0.4", + "resolve": "^1.10.1", + "semver": "^6.1.0" + }, + "dependencies": { + "eslint-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz", + "integrity": "sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "ignore": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", + "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "eslint-plugin-prettier": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.2.tgz", + "integrity": "sha512-GlolCC9y3XZfv3RQfwGew7NnuFDKsfI4lbvRK+PIIo23SFH+LemGs4cKwzAaRa+Mdb+lQO/STaIayno8T5sJJA==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, + "eslint-plugin-promise": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz", + "integrity": "sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==", + "dev": true + }, + "eslint-plugin-react": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.18.3.tgz", + "integrity": "sha512-Bt56LNHAQCoou88s8ViKRjMB2+36XRejCQ1VoLj716KI1MoE99HpTVvIThJ0rvFmG4E4Gsq+UgToEjn+j044Bg==", + "dev": true, + "requires": { + "array-includes": "^3.1.1", + "doctrine": "^2.1.0", + "has": "^1.0.3", + "jsx-ast-utils": "^2.2.3", + "object.entries": "^1.1.1", + "object.fromentries": "^2.0.2", + "object.values": "^1.1.1", + "prop-types": "^15.7.2", + "resolve": "^1.14.2", + "string.prototype.matchall": "^4.0.2" + }, + "dependencies": { + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "eslint-plugin-standard": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.0.1.tgz", + "integrity": "sha512-v/KBnfyaOMPmZc/dmc6ozOdWqekGp7bBGq4jLAecEfPGmfKiWS4sA8sC0LqiV9w5qmXAtXVn4M3p1jSyhY85SQ==", + "dev": true + }, + "eslint-scope": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + }, + "espree": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz", + "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==", + "dev": true, + "requires": { + "acorn": "^7.1.0", + "acorn-jsx": "^5.1.0", + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "dev": true + } + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.1.0.tgz", + "integrity": "sha512-MxYW9xKmROWF672KqjO75sszsA8Mxhw06YFeS5VHlB98KDHbOSurm3ArsjO60Eaf3QmGMCP1yn+0JQkNLo/97Q==", + "dev": true, + "requires": { + "estraverse": "^4.0.0" + } + }, + "esrecurse": { + "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.1.0" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, "event-target-shim": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", @@ -788,6 +1798,17 @@ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -798,26 +1819,107 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, "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=" }, + "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 + }, "fast-text-encoding": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.0.tgz", "integrity": "sha512-R9bHCvweUxxwkDwhjav5vxpFvdPGlVngtqmx4pIZfSUhM/Q4NiIUHB456BAf+Q1Nwu3HEZYONtu+Rya+af4jiQ==" }, + "figures": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.1.0.tgz", + "integrity": "sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, "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==" }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, "findit2": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/findit2/-/findit2-2.2.3.tgz", "integrity": "sha1-WKRmaX34piBc39vzlVNri9d3pfY=" }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "flatted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "dev": true + }, "follow-redirects": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", @@ -883,6 +1985,18 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": 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 + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, "gaxios": { "version": "1.8.4", "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-1.8.4.tgz", @@ -903,6 +2017,18 @@ "json-bigint": "^0.3.0" } }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-stdin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", + "dev": true + }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -931,6 +2057,21 @@ "path-is-absolute": "^1.0.0" } }, + "glob-parent": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", + "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, "google-auth-library": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-3.1.2.tgz", @@ -956,6 +2097,12 @@ "pify": "^4.0.0" } }, + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + }, "gtoken": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-2.3.3.tgz", @@ -989,12 +2136,44 @@ "har-schema": "^2.0.0" } }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } + } + }, "has-flag": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", "dev": true }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, "hawk": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.0.0.tgz", @@ -1023,8 +2202,13 @@ "version": "0.9.1", "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", "integrity": "sha1-PTIkYrrfB3Fup+uFuviAec3c5QU=", - "dev": true, - "optional": true + "dev": true + }, + "hosted-git-info": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz", + "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==", + "dev": true }, "http-signature": { "version": "0.10.1", @@ -1062,6 +2246,51 @@ } } }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + } + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -1076,16 +2305,117 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, + "inquirer": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.4.tgz", + "integrity": "sha512-Bu5Td5+j11sCkqfqmUTiwv+tWisMtP0L7Q8WrqA2C/BbBhy1YTdFrvjjlrKq8oagA/tLQBski2Gcx/Sqyi2qSQ==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^2.4.2", + "cli-cursor": "^3.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.15", + "mute-stream": "0.0.8", + "run-async": "^2.2.0", + "rxjs": "^6.5.3", + "string-width": "^4.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + } + }, + "internal-slot": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.2.tgz", + "integrity": "sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g==", + "dev": true, + "requires": { + "es-abstract": "^1.17.0-next.1", + "has": "^1.0.3", + "side-channel": "^1.0.2" + } + }, "is": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/is/-/is-3.3.0.tgz", "integrity": "sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg==" }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, "is-buffer": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==" }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -1096,16 +2426,44 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, "json-bigint": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-0.3.0.tgz", @@ -1124,6 +2482,12 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -1147,6 +2511,16 @@ } } }, + "jsx-ast-utils": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.2.3.tgz", + "integrity": "sha512-EdIHFMm+1BPynpKOpdPqiOsvnIrInRGJD7bzPZdPkjitQEqpdpUuFpq4T0npZFKTiB3RhWFdGN+oqOJIdhDhQA==", + "dev": true, + "requires": { + "array-includes": "^3.0.3", + "object.assign": "^4.1.0" + } + }, "just-extend": { "version": "1.1.27", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-1.1.27.tgz", @@ -1172,11 +2546,75 @@ "safe-buffer": "^5.0.1" } }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "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.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "lodash.pickby": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.pickby/-/lodash.pickby-4.6.0.tgz", "integrity": "sha1-feoh2MGNdwOifHBMFdO4SmfjOv8=" }, + "lodash.unescape": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz", + "integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=", + "dev": true + }, "logger-sharelatex": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/logger-sharelatex/-/logger-sharelatex-1.7.0.tgz", @@ -1316,6 +2754,64 @@ } } }, + "loglevel": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.7.tgz", + "integrity": "sha512-cY2eLFrQSAfVPhCgH1s7JI73tMbg9YC3v3+ZHVW67sBS7UxWzNEk/ZBbSfLykBWHp33dqqtOv82gjhKEi81T/A==", + "dev": true + }, + "loglevel-colored-level-prefix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/loglevel-colored-level-prefix/-/loglevel-colored-level-prefix-1.0.0.tgz", + "integrity": "sha1-akAhj9x64V/HbD0PPmdsRlOIYD4=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "loglevel": "^1.4.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "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=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "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 + } + } + }, "lolex": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.6.0.tgz", @@ -1327,6 +2823,15 @@ "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -1349,6 +2854,30 @@ "statsd-parser": "~0.0.4" } }, + "make-plural": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/make-plural/-/make-plural-4.3.0.tgz", + "integrity": "sha512-xTYd4JVHpSCW+aqDof6w/MebaMVNTVYBZhbB/vi513xXdiPT92JMVCo0Jq8W2UZnzYRFeVbQiQ+I25l13JuKvA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true, + "optional": true + } + } + }, + "map-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.1.0.tgz", + "integrity": "sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g==", + "dev": true + }, "merge-descriptors": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-0.0.2.tgz", @@ -1359,6 +2888,29 @@ "resolved": "https://registry.npmjs.org/mersenne/-/mersenne-0.0.4.tgz", "integrity": "sha1-QB/ex+whzbngPNPTAhOY2iGycIU=" }, + "messageformat": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/messageformat/-/messageformat-2.3.0.tgz", + "integrity": "sha512-uTzvsv0lTeQxYI2y1NPa1lItL5VRI8Gb93Y2K2ue5gBPyrbJxfDi/EYWxh2PKv5yO42AJeeqblS9MJSh/IEk4w==", + "dev": true, + "requires": { + "make-plural": "^4.3.0", + "messageformat-formatters": "^2.0.1", + "messageformat-parser": "^4.1.2" + } + }, + "messageformat-formatters": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/messageformat-formatters/-/messageformat-formatters-2.0.1.tgz", + "integrity": "sha512-E/lQRXhtHwGuiQjI7qxkLp8AHbMD5r2217XNe/SREbBlSawe0lOqsFb7rflZJmlQFSULNLIqlcjjsCPlB3m3Mg==", + "dev": true + }, + "messageformat-parser": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/messageformat-parser/-/messageformat-parser-4.1.2.tgz", + "integrity": "sha512-7dWuifeyldz7vhEuL96Kwq1fhZXBW+TUfbnHN4UCrCxoXQTYjHnR78eI66Gk9LaLLsAvzPNVJBaa66DRfFNaiA==", + "dev": true + }, "methods": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/methods/-/methods-0.1.0.tgz", @@ -1403,6 +2955,12 @@ "mime-db": "1.40.0" } }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -1559,6 +3117,12 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, "mv": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", @@ -1581,6 +3145,12 @@ "integrity": "sha1-IKMYwwy0X3H+et+/eyHJnBRy7xE=", "dev": true }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, "ncp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", @@ -1592,6 +3162,12 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.9.tgz", "integrity": "sha1-kuRrbbU8fkIe1koryU8IvnYw3z8=" }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, "nise": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/nise/-/nise-1.3.3.tgz", @@ -1638,6 +3214,18 @@ "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", "dev": true }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, "oauth-sign": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz", @@ -1645,6 +3233,72 @@ "dev": true, "optional": true }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.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.entries": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.1.tgz", + "integrity": "sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "object.fromentries": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.2.tgz", + "integrity": "sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "object.values": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1653,6 +3307,35 @@ "wrappy": "1" } }, + "onetime": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", + "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": 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", + "word-wrap": "~1.2.3" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, "p-limit": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", @@ -1661,16 +3344,60 @@ "p-try": "^2.0.0" } }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + }, + "dependencies": { + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-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 + } + } + }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, "parse-duration": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/parse-duration/-/parse-duration-0.1.1.tgz", "integrity": "sha1-ExFN3JiRwezSgANiRFVN5DZHoiY=" }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, "parse-mongo-url": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/parse-mongo-url/-/parse-mongo-url-1.1.1.tgz", @@ -1686,11 +3413,29 @@ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.0.1.tgz", "integrity": "sha1-Llfc5u/dN8NRhwEDCUTCK/OIt7Q=" }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", @@ -1701,6 +3446,23 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.2.tgz", "integrity": "sha1-mysVH5zDAYye6lDKlXKeBXgXErQ=" }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -1711,6 +3473,618 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + }, + "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 + }, + "prettier": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", + "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", + "dev": true + }, + "prettier-eslint": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/prettier-eslint/-/prettier-eslint-9.0.1.tgz", + "integrity": "sha512-KZT65QTosSAqBBqmrC+RpXbsMRe7Os2YSR9cAfFbDlyPAopzA/S5bioiZ3rpziNQNSJaOxmtXSx07EQ+o2Dlug==", + "dev": true, + "requires": { + "@typescript-eslint/parser": "^1.10.2", + "common-tags": "^1.4.0", + "core-js": "^3.1.4", + "dlv": "^1.1.0", + "eslint": "^5.0.0", + "indent-string": "^4.0.0", + "lodash.merge": "^4.6.0", + "loglevel-colored-level-prefix": "^1.0.0", + "prettier": "^1.7.0", + "pretty-format": "^23.0.1", + "require-relative": "^0.8.7", + "typescript": "^3.2.1", + "vue-eslint-parser": "^2.0.2" + }, + "dependencies": { + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "eslint": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", + "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.9.1", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^4.0.3", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^5.0.1", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.2.2", + "js-yaml": "^3.13.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^5.5.1", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0" + } + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "espree": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", + "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", + "dev": true, + "requires": { + "acorn": "^6.0.7", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "mimic-fn": { + "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 + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + } + } + }, + "prettier-eslint-cli": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/prettier-eslint-cli/-/prettier-eslint-cli-5.0.0.tgz", + "integrity": "sha512-cei9UbN1aTrz3sQs88CWpvY/10PYTevzd76zoG1tdJ164OhmNTFRKPTOZrutVvscoQWzbnLKkviS3gu5JXwvZg==", + "dev": true, + "requires": { + "arrify": "^2.0.1", + "boolify": "^1.0.0", + "camelcase-keys": "^6.0.0", + "chalk": "^2.4.2", + "common-tags": "^1.8.0", + "core-js": "^3.1.4", + "eslint": "^5.0.0", + "find-up": "^4.1.0", + "get-stdin": "^7.0.0", + "glob": "^7.1.4", + "ignore": "^5.1.2", + "lodash.memoize": "^4.1.2", + "loglevel-colored-level-prefix": "^1.0.0", + "messageformat": "^2.2.1", + "prettier-eslint": "^9.0.0", + "rxjs": "^6.5.2", + "yargs": "^13.2.4" + }, + "dependencies": { + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "eslint": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", + "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.9.1", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^4.0.3", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^5.0.1", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.2.2", + "js-yaml": "^3.13.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^5.5.1", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0" + }, + "dependencies": { + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + } + } + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "espree": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", + "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", + "dev": true, + "requires": { + "acorn": "^6.0.7", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "get-stdin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", + "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "ignore": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", + "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", + "dev": true + }, + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "mimic-fn": { + "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 + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + } + } + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, + "pretty-format": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz", + "integrity": "sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0", + "ansi-styles": "^3.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + } + } + }, "pretty-ms": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-4.0.0.tgz", @@ -1724,6 +4098,12 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, "prom-client": { "version": "11.5.1", "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-11.5.1.tgz", @@ -1732,6 +4112,17 @@ "tdigest": "^0.1.1" } }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "dev": true, + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, "protobufjs": { "version": "6.8.8", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.8.tgz", @@ -1774,6 +4165,18 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz", "integrity": "sha1-bgFQmP9RlouKPIGQAdXyyJvEsQc=" }, + "quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true + }, + "ramda": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.26.1.tgz", + "integrity": "sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ==", + "dev": true + }, "range-parser": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.0.tgz", @@ -1812,6 +4215,33 @@ "string_decoder": "0.10" } }, + "react-is": { + "version": "16.12.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz", + "integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==", + "dev": true + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", @@ -1841,6 +4271,28 @@ } } }, + "regenerator-runtime": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", + "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==", + "dev": true + }, + "regexp.prototype.flags": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", + "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, "request": { "version": "2.34.0", "resolved": "https://registry.npmjs.org/request/-/request-2.34.0.tgz", @@ -1861,6 +4313,12 @@ "tunnel-agent": "~0.3.0" } }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, "require-in-the-middle": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-4.0.0.tgz", @@ -1892,6 +4350,18 @@ "integrity": "sha1-rW8wwTvs15cBDEaK+ndcDAprR/o=", "dev": true }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "require-relative": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz", + "integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=", + "dev": true + }, "require_optional": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", @@ -1914,6 +4384,16 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, "retry-axios": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/retry-axios/-/retry-axios-0.3.2.tgz", @@ -1936,6 +4416,24 @@ "glob": "^6.0.1" } }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "^2.1.0" + } + }, + "rxjs": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz", + "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -2009,6 +4507,12 @@ "send": "0.3.0" } }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, "settings-sharelatex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/settings-sharelatex/-/settings-sharelatex-1.1.0.tgz", @@ -2024,11 +4528,42 @@ } } }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, "shimmer": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" }, + "side-channel": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.2.tgz", + "integrity": "sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA==", + "dev": true, + "requires": { + "es-abstract": "^1.17.0-next.1", + "object-inspect": "^1.7.0" + } + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, "sinon": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/sinon/-/sinon-3.2.1.tgz", @@ -2075,6 +4610,25 @@ } } }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + } + } + }, "sntp": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", @@ -2090,6 +4644,38 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true + }, "split": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", @@ -2098,6 +4684,12 @@ "through": "2" } }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, "sshpk": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", @@ -2144,11 +4736,96 @@ "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "string.prototype.matchall": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz", + "integrity": "sha512-N/jp6O5fMf9os0JU3E72Qhf590RSRZU/ungsL/qJUYVTNv7hTG0P/dbPjxINVN9jpscu3nzYwKESU3P3RY5tOg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "has-symbols": "^1.0.1", + "internal-slot": "^1.0.2", + "regexp.prototype.flags": "^1.3.0", + "side-channel": "^1.0.2" + } + }, + "string.prototype.trimleft": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", + "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", + "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + } + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-json-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -2158,6 +4835,61 @@ "has-flag": "^2.0.0" } }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz", + "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + } + } + }, "tdigest": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.1.tgz", @@ -2189,6 +4921,12 @@ "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", "dev": true }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -2208,6 +4946,21 @@ "resolved": "https://registry.npmjs.org/thunky/-/thunky-0.1.0.tgz", "integrity": "sha1-vzAUaCTituZ7Dy16Ssi+smkIaE4=" }, + "tmp": { + "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" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, "to-mongodb-core": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-mongodb-core/-/to-mongodb-core-2.0.0.tgz", @@ -2223,6 +4976,12 @@ "punycode": "^1.4.1" } }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", + "dev": true + }, "tunnel-agent": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.3.0.tgz", @@ -2235,12 +4994,27 @@ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, + "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-detect": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", "dev": true }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, "type-is": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.1.0.tgz", @@ -2249,6 +5023,12 @@ "mime": "~1.2.11" } }, + "typescript": { + "version": "3.7.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.5.tgz", + "integrity": "sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw==", + "dev": true + }, "underscore": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", @@ -2279,6 +5059,22 @@ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=" }, + "v8-compile-cache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", + "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", @@ -2296,20 +5092,247 @@ } } }, + "vue-eslint-parser": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-2.0.3.tgz", + "integrity": "sha512-ZezcU71Owm84xVF6gfurBQUGg8WQ+WZGxgDEQu1IHFBZNx7BFZg3L1yHxrCBNNwbwFtE1GuvfJKMtb6Xuwc/Bw==", + "dev": true, + "requires": { + "debug": "^3.1.0", + "eslint-scope": "^3.7.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^3.5.2", + "esquery": "^1.0.0", + "lodash": "^4.17.4" + }, + "dependencies": { + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "^3.0.4" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "eslint-scope": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "espree": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "dev": true, + "requires": { + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + } + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" }, + "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 + }, "yallist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" + }, + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + }, + "dependencies": { + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + } + } + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } } } } diff --git a/services/docstore/package.json b/services/docstore/package.json index ff0950cf27..5181dbbc65 100644 --- a/services/docstore/package.json +++ b/services/docstore/package.json @@ -30,9 +30,27 @@ "underscore": "~1.6.0" }, "devDependencies": { + "babel-eslint": "^10.0.3", "bunyan": "~0.22.3", "chai": "~1.9.1", + "eslint": "^6.6.0", + "eslint-config-prettier": "^6.10.0", + "eslint-config-standard": "^14.1.0", + "eslint-config-standard-jsx": "^8.1.0", + "eslint-config-standard-react": "^9.2.0", + "eslint-plugin-chai-expect": "^2.1.0", + "eslint-plugin-chai-friendly": "^0.5.0", + "eslint-plugin-import": "^2.20.1", + "eslint-plugin-jsx-a11y": "^6.2.3", + "eslint-plugin-mocha": "^6.2.2", + "eslint-plugin-node": "^11.0.0", + "eslint-plugin-prettier": "^3.1.2", + "eslint-plugin-promise": "^4.2.1", + "eslint-plugin-react": "^7.18.3", + "eslint-plugin-standard": "^4.0.1", "mocha": "^4.0.1", + "prettier": "^1.19.1", + "prettier-eslint-cli": "^5.0.0", "request": "~2.34.0", "sandboxed-module": "~0.3.0", "sinon": "~3.2.1" From 88badb15c4911a0ed97dd6f05d81952b9338716e Mon Sep 17 00:00:00 2001 From: decaffeinate Date: Sun, 16 Feb 2020 14:01:44 +0000 Subject: [PATCH 04/27] decaffeinate: Rename DocArchiveManager.coffee and 7 other files from .coffee to .js --- .../app/coffee/{DocArchiveManager.coffee => DocArchiveManager.js} | 0 services/docstore/app/coffee/{DocManager.coffee => DocManager.js} | 0 services/docstore/app/coffee/{Errors.coffee => Errors.js} | 0 .../app/coffee/{HealthChecker.coffee => HealthChecker.js} | 0 .../app/coffee/{HttpController.coffee => HttpController.js} | 0 .../docstore/app/coffee/{MongoManager.coffee => MongoManager.js} | 0 .../docstore/app/coffee/{RangeManager.coffee => RangeManager.js} | 0 services/docstore/app/coffee/{mongojs.coffee => mongojs.js} | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename services/docstore/app/coffee/{DocArchiveManager.coffee => DocArchiveManager.js} (100%) rename services/docstore/app/coffee/{DocManager.coffee => DocManager.js} (100%) rename services/docstore/app/coffee/{Errors.coffee => Errors.js} (100%) rename services/docstore/app/coffee/{HealthChecker.coffee => HealthChecker.js} (100%) rename services/docstore/app/coffee/{HttpController.coffee => HttpController.js} (100%) rename services/docstore/app/coffee/{MongoManager.coffee => MongoManager.js} (100%) rename services/docstore/app/coffee/{RangeManager.coffee => RangeManager.js} (100%) rename services/docstore/app/coffee/{mongojs.coffee => mongojs.js} (100%) diff --git a/services/docstore/app/coffee/DocArchiveManager.coffee b/services/docstore/app/coffee/DocArchiveManager.js similarity index 100% rename from services/docstore/app/coffee/DocArchiveManager.coffee rename to services/docstore/app/coffee/DocArchiveManager.js diff --git a/services/docstore/app/coffee/DocManager.coffee b/services/docstore/app/coffee/DocManager.js similarity index 100% rename from services/docstore/app/coffee/DocManager.coffee rename to services/docstore/app/coffee/DocManager.js diff --git a/services/docstore/app/coffee/Errors.coffee b/services/docstore/app/coffee/Errors.js similarity index 100% rename from services/docstore/app/coffee/Errors.coffee rename to services/docstore/app/coffee/Errors.js diff --git a/services/docstore/app/coffee/HealthChecker.coffee b/services/docstore/app/coffee/HealthChecker.js similarity index 100% rename from services/docstore/app/coffee/HealthChecker.coffee rename to services/docstore/app/coffee/HealthChecker.js diff --git a/services/docstore/app/coffee/HttpController.coffee b/services/docstore/app/coffee/HttpController.js similarity index 100% rename from services/docstore/app/coffee/HttpController.coffee rename to services/docstore/app/coffee/HttpController.js diff --git a/services/docstore/app/coffee/MongoManager.coffee b/services/docstore/app/coffee/MongoManager.js similarity index 100% rename from services/docstore/app/coffee/MongoManager.coffee rename to services/docstore/app/coffee/MongoManager.js diff --git a/services/docstore/app/coffee/RangeManager.coffee b/services/docstore/app/coffee/RangeManager.js similarity index 100% rename from services/docstore/app/coffee/RangeManager.coffee rename to services/docstore/app/coffee/RangeManager.js diff --git a/services/docstore/app/coffee/mongojs.coffee b/services/docstore/app/coffee/mongojs.js similarity index 100% rename from services/docstore/app/coffee/mongojs.coffee rename to services/docstore/app/coffee/mongojs.js From afa2577381197c9e1922ffb014281660d264bb2d Mon Sep 17 00:00:00 2001 From: decaffeinate Date: Sun, 16 Feb 2020 14:01:46 +0000 Subject: [PATCH 05/27] decaffeinate: Convert DocArchiveManager.coffee and 7 other files to JS --- .../docstore/app/coffee/DocArchiveManager.js | 354 ++++++++++-------- services/docstore/app/coffee/DocManager.js | 274 ++++++++------ services/docstore/app/coffee/Errors.js | 18 +- services/docstore/app/coffee/HealthChecker.js | 99 ++--- .../docstore/app/coffee/HttpController.js | 346 ++++++++++------- services/docstore/app/coffee/MongoManager.js | 146 +++++--- services/docstore/app/coffee/RangeManager.js | 87 +++-- services/docstore/app/coffee/mongojs.js | 11 +- 8 files changed, 796 insertions(+), 539 deletions(-) diff --git a/services/docstore/app/coffee/DocArchiveManager.js b/services/docstore/app/coffee/DocArchiveManager.js index 1fb6fb2657..e3c048558e 100644 --- a/services/docstore/app/coffee/DocArchiveManager.js +++ b/services/docstore/app/coffee/DocArchiveManager.js @@ -1,156 +1,208 @@ -MongoManager = require "./MongoManager" -Errors = require "./Errors" -logger = require "logger-sharelatex" -_ = require "underscore" -async = require "async" -settings = require("settings-sharelatex") -request = require("request") -crypto = require("crypto") -RangeManager = require("./RangeManager") -thirtySeconds = 30 * 1000 +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS207: Consider shorter variations of null checks + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +let DocArchive; +const MongoManager = require("./MongoManager"); +const Errors = require("./Errors"); +const logger = require("logger-sharelatex"); +const _ = require("underscore"); +const async = require("async"); +const settings = require("settings-sharelatex"); +const request = require("request"); +const crypto = require("crypto"); +const RangeManager = require("./RangeManager"); +const thirtySeconds = 30 * 1000; -module.exports = DocArchive = +module.exports = (DocArchive = { - archiveAllDocs: (project_id, callback = (err, docs) ->) -> - MongoManager.getProjectsDocs project_id, {include_deleted: true}, {lines: true, ranges: true, rev: true, inS3: true}, (err, docs) -> - if err? - return callback(err) - else if !docs? - return callback new Errors.NotFoundError("No docs for project #{project_id}") - docs = _.filter docs, (doc)-> doc.inS3 != true - jobs = _.map docs, (doc) -> - (cb)-> - DocArchive.archiveDoc project_id, doc, cb - async.parallelLimit jobs, 5, callback + archiveAllDocs(project_id, callback) { + if (callback == null) { callback = function(err, docs) {}; } + return MongoManager.getProjectsDocs(project_id, {include_deleted: true}, {lines: true, ranges: true, rev: true, inS3: true}, function(err, docs) { + if (err != null) { + return callback(err); + } else if ((docs == null)) { + return callback(new Errors.NotFoundError(`No docs for project ${project_id}`)); + } + docs = _.filter(docs, doc => doc.inS3 !== true); + const jobs = _.map(docs, doc => cb => DocArchive.archiveDoc(project_id, doc, cb)); + return async.parallelLimit(jobs, 5, callback); + }); + }, - archiveDoc: (project_id, doc, callback)-> - logger.log project_id: project_id, doc_id: doc._id, "sending doc to s3" - try - options = DocArchive.buildS3Options(project_id+"/"+doc._id) - catch e - return callback e - DocArchive._mongoDocToS3Doc doc, (error, json_doc) -> - return callback(error) if error? - options.body = json_doc - options.headers = - 'Content-Type': "application/json" - request.put options, (err, res) -> - if err? || res.statusCode != 200 - logger.err err:err, res:res, project_id:project_id, doc_id: doc._id, statusCode: res?.statusCode, "something went wrong archiving doc in aws" - return callback new Error("Error in S3 request") - md5lines = crypto.createHash("md5").update(json_doc, "utf8").digest("hex") - md5response = res.headers.etag.toString().replace(/\"/g, '') - if md5lines != md5response - logger.err responseMD5:md5response, linesMD5:md5lines, project_id:project_id, doc_id: doc?._id, "err in response md5 from s3" - return callback new Error("Error in S3 md5 response") - MongoManager.markDocAsArchived doc._id, doc.rev, (err) -> - return callback(err) if err? - callback() - - unArchiveAllDocs: (project_id, callback = (err) ->) -> - MongoManager.getArchivedProjectDocs project_id, (err, docs) -> - if err? - logger.err err:err, project_id:project_id, "error unarchiving all docs" - return callback(err) - else if !docs? - return callback new Errors.NotFoundError("No docs for project #{project_id}") - jobs = _.map docs, (doc) -> - (cb)-> - if !doc.inS3? - return cb() - else - DocArchive.unarchiveDoc project_id, doc._id, cb - async.parallelLimit jobs, 5, callback - - unarchiveDoc: (project_id, doc_id, callback)-> - logger.log project_id: project_id, doc_id: doc_id, "getting doc from s3" - try - options = DocArchive.buildS3Options(project_id+"/"+doc_id) - catch e - return callback e - options.json = true - request.get options, (err, res, doc)-> - if err? || res.statusCode != 200 - logger.err err:err, res:res, project_id:project_id, doc_id:doc_id, "something went wrong unarchiving doc from aws" - return callback new Errors.NotFoundError("Error in S3 request") - DocArchive._s3DocToMongoDoc doc, (error, mongo_doc) -> - return callback(error) if error? - MongoManager.upsertIntoDocCollection project_id, doc_id.toString(), mongo_doc, (err) -> - return callback(err) if err? - logger.log project_id: project_id, doc_id: doc_id, "deleting doc from s3" - DocArchive._deleteDocFromS3 project_id, doc_id, callback - - destroyAllDocs: (project_id, callback = (err) ->) -> - MongoManager.getProjectsDocs project_id, {include_deleted: true}, {_id: 1}, (err, docs) -> - if err? - logger.err err:err, project_id:project_id, "error getting project's docs" - return callback(err) - else if !docs? - return callback() - jobs = _.map docs, (doc) -> - (cb)-> - DocArchive.destroyDoc(project_id, doc._id, cb) - async.parallelLimit jobs, 5, callback - - destroyDoc: (project_id, doc_id, callback)-> - logger.log project_id: project_id, doc_id: doc_id, "removing doc from mongo and s3" - MongoManager.findDoc project_id, doc_id, {inS3: 1}, (error, doc) -> - return callback error if error? - return callback new Errors.NotFoundError("Doc not found in Mongo") unless doc? - if doc.inS3 == true - DocArchive._deleteDocFromS3 project_id, doc_id, (err) -> - return err if err? - MongoManager.destroyDoc doc_id, callback - else - MongoManager.destroyDoc doc_id, callback - - _deleteDocFromS3: (project_id, doc_id, callback) -> - try - options = DocArchive.buildS3Options(project_id+"/"+doc_id) - catch e - return callback e - options.json = true - request.del options, (err, res, body)-> - if err? || res.statusCode != 204 - logger.err err:err, res:res, project_id:project_id, doc_id:doc_id, "something went wrong deleting doc from aws" - return callback new Error("Error in S3 request") - callback() - - _s3DocToMongoDoc: (doc, callback = (error, mongo_doc) ->) -> - mongo_doc = {} - if doc.schema_v == 1 and doc.lines? - mongo_doc.lines = doc.lines - if doc.ranges? - mongo_doc.ranges = RangeManager.jsonRangesToMongo(doc.ranges) - else if doc instanceof Array - mongo_doc.lines = doc - else - return callback(new Error("I don't understand the doc format in s3")) - return callback null, mongo_doc - - _mongoDocToS3Doc: (doc, callback = (error, s3_doc) ->) -> - if !doc.lines? - return callback(new Error("doc has no lines")) - json = JSON.stringify({ - lines: doc.lines - ranges: doc.ranges - schema_v: 1 - }) - if json.indexOf("\u0000") != -1 - error = new Error("null bytes detected") - logger.err {err: error, doc, json}, error.message - return callback(error) - return callback null, json - - buildS3Options: (key)-> - if !settings.docstore.s3? - throw new Error("S3 settings are not configured") - return { - aws: - key: settings.docstore.s3.key - secret: settings.docstore.s3.secret - bucket: settings.docstore.s3.bucket - timeout: thirtySeconds - uri:"https://#{settings.docstore.s3.bucket}.s3.amazonaws.com/#{key}" + archiveDoc(project_id, doc, callback){ + let options; + logger.log({project_id, doc_id: doc._id}, "sending doc to s3"); + try { + options = DocArchive.buildS3Options(project_id+"/"+doc._id); + } catch (e) { + return callback(e); } + return DocArchive._mongoDocToS3Doc(doc, function(error, json_doc) { + if (error != null) { return callback(error); } + options.body = json_doc; + options.headers = + {'Content-Type': "application/json"}; + return request.put(options, function(err, res) { + if ((err != null) || (res.statusCode !== 200)) { + logger.err({err, res, project_id, doc_id: doc._id, statusCode: (res != null ? res.statusCode : undefined)}, "something went wrong archiving doc in aws"); + return callback(new Error("Error in S3 request")); + } + const md5lines = crypto.createHash("md5").update(json_doc, "utf8").digest("hex"); + const md5response = res.headers.etag.toString().replace(/\"/g, ''); + if (md5lines !== md5response) { + logger.err({responseMD5:md5response, linesMD5:md5lines, project_id, doc_id: (doc != null ? doc._id : undefined)}, "err in response md5 from s3"); + return callback(new Error("Error in S3 md5 response")); + } + return MongoManager.markDocAsArchived(doc._id, doc.rev, function(err) { + if (err != null) { return callback(err); } + return callback(); + }); + }); + }); + }, + + unArchiveAllDocs(project_id, callback) { + if (callback == null) { callback = function(err) {}; } + return MongoManager.getArchivedProjectDocs(project_id, function(err, docs) { + if (err != null) { + logger.err({err, project_id}, "error unarchiving all docs"); + return callback(err); + } else if ((docs == null)) { + return callback(new Errors.NotFoundError(`No docs for project ${project_id}`)); + } + const jobs = _.map(docs, doc => (function(cb) { + if ((doc.inS3 == null)) { + return cb(); + } else { + return DocArchive.unarchiveDoc(project_id, doc._id, cb); + } + })); + return async.parallelLimit(jobs, 5, callback); + }); + }, + + unarchiveDoc(project_id, doc_id, callback){ + let options; + logger.log({project_id, doc_id}, "getting doc from s3"); + try { + options = DocArchive.buildS3Options(project_id+"/"+doc_id); + } catch (e) { + return callback(e); + } + options.json = true; + return request.get(options, function(err, res, doc){ + if ((err != null) || (res.statusCode !== 200)) { + logger.err({err, res, project_id, doc_id}, "something went wrong unarchiving doc from aws"); + return callback(new Errors.NotFoundError("Error in S3 request")); + } + return DocArchive._s3DocToMongoDoc(doc, function(error, mongo_doc) { + if (error != null) { return callback(error); } + return MongoManager.upsertIntoDocCollection(project_id, doc_id.toString(), mongo_doc, function(err) { + if (err != null) { return callback(err); } + logger.log({project_id, doc_id}, "deleting doc from s3"); + return DocArchive._deleteDocFromS3(project_id, doc_id, callback); + }); + }); + }); + }, + + destroyAllDocs(project_id, callback) { + if (callback == null) { callback = function(err) {}; } + return MongoManager.getProjectsDocs(project_id, {include_deleted: true}, {_id: 1}, function(err, docs) { + if (err != null) { + logger.err({err, project_id}, "error getting project's docs"); + return callback(err); + } else if ((docs == null)) { + return callback(); + } + const jobs = _.map(docs, doc => cb => DocArchive.destroyDoc(project_id, doc._id, cb)); + return async.parallelLimit(jobs, 5, callback); + }); + }, + + destroyDoc(project_id, doc_id, callback){ + logger.log({project_id, doc_id}, "removing doc from mongo and s3"); + return MongoManager.findDoc(project_id, doc_id, {inS3: 1}, function(error, doc) { + if (error != null) { return callback(error); } + if (doc == null) { return callback(new Errors.NotFoundError("Doc not found in Mongo")); } + if (doc.inS3 === true) { + return DocArchive._deleteDocFromS3(project_id, doc_id, function(err) { + if (err != null) { return err; } + return MongoManager.destroyDoc(doc_id, callback); + }); + } else { + return MongoManager.destroyDoc(doc_id, callback); + } + }); + }, + + _deleteDocFromS3(project_id, doc_id, callback) { + let options; + try { + options = DocArchive.buildS3Options(project_id+"/"+doc_id); + } catch (e) { + return callback(e); + } + options.json = true; + return request.del(options, function(err, res, body){ + if ((err != null) || (res.statusCode !== 204)) { + logger.err({err, res, project_id, doc_id}, "something went wrong deleting doc from aws"); + return callback(new Error("Error in S3 request")); + } + return callback(); + }); + }, + + _s3DocToMongoDoc(doc, callback) { + if (callback == null) { callback = function(error, mongo_doc) {}; } + const mongo_doc = {}; + if ((doc.schema_v === 1) && (doc.lines != null)) { + mongo_doc.lines = doc.lines; + if (doc.ranges != null) { + mongo_doc.ranges = RangeManager.jsonRangesToMongo(doc.ranges); + } + } else if (doc instanceof Array) { + mongo_doc.lines = doc; + } else { + return callback(new Error("I don't understand the doc format in s3")); + } + return callback(null, mongo_doc); + }, + + _mongoDocToS3Doc(doc, callback) { + if (callback == null) { callback = function(error, s3_doc) {}; } + if ((doc.lines == null)) { + return callback(new Error("doc has no lines")); + } + const json = JSON.stringify({ + lines: doc.lines, + ranges: doc.ranges, + schema_v: 1 + }); + if (json.indexOf("\u0000") !== -1) { + const error = new Error("null bytes detected"); + logger.err({err: error, doc, json}, error.message); + return callback(error); + } + return callback(null, json); + }, + + buildS3Options(key){ + if ((settings.docstore.s3 == null)) { + throw new Error("S3 settings are not configured"); + } + return { + aws: { + key: settings.docstore.s3.key, + secret: settings.docstore.s3.secret, + bucket: settings.docstore.s3.bucket + }, + timeout: thirtySeconds, + uri:`https://${settings.docstore.s3.bucket}.s3.amazonaws.com/${key}` + }; + } +}); diff --git a/services/docstore/app/coffee/DocManager.js b/services/docstore/app/coffee/DocManager.js index be55a23e44..8bb86d8eb3 100644 --- a/services/docstore/app/coffee/DocManager.js +++ b/services/docstore/app/coffee/DocManager.js @@ -1,130 +1,184 @@ -MongoManager = require "./MongoManager" -Errors = require "./Errors" -logger = require "logger-sharelatex" -_ = require "underscore" -DocArchive = require "./DocArchiveManager" -RangeManager = require "./RangeManager" +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS207: Consider shorter variations of null checks + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +let DocManager; +const MongoManager = require("./MongoManager"); +const Errors = require("./Errors"); +const logger = require("logger-sharelatex"); +const _ = require("underscore"); +const DocArchive = require("./DocArchiveManager"); +const RangeManager = require("./RangeManager"); -module.exports = DocManager = +module.exports = (DocManager = { - # TODO: For historical reasons, the doc version is currently stored in the docOps - # collection (which is all that this collection contains). In future, we should - # migrate this version property to be part of the docs collection, to guarantee - # consitency between lines and version when writing/reading, and for a simpler schema. - _getDoc: (project_id, doc_id, filter = {}, callback = (error, doc) ->) -> - if filter.inS3 != true - return callback("must include inS3 when getting doc") + // TODO: For historical reasons, the doc version is currently stored in the docOps + // collection (which is all that this collection contains). In future, we should + // migrate this version property to be part of the docs collection, to guarantee + // consitency between lines and version when writing/reading, and for a simpler schema. + _getDoc(project_id, doc_id, filter, callback) { + if (filter == null) { filter = {}; } + if (callback == null) { callback = function(error, doc) {}; } + if (filter.inS3 !== true) { + return callback("must include inS3 when getting doc"); + } - MongoManager.findDoc project_id, doc_id, filter, (err, doc)-> - if err? - return callback(err) - else if !doc? - return callback new Errors.NotFoundError("No such doc: #{doc_id} in project #{project_id}") - else if doc?.inS3 - DocArchive.unarchiveDoc project_id, doc_id, (err)-> - if err? - logger.err err:err, project_id:project_id, doc_id:doc_id, "error unarchiving doc" - return callback(err) - DocManager._getDoc project_id, doc_id, filter, callback - else - if filter.version - MongoManager.getDocVersion doc_id, (error, version) -> - return callback(error) if error? - doc.version = version - callback err, doc - else - callback err, doc + return MongoManager.findDoc(project_id, doc_id, filter, function(err, doc){ + if (err != null) { + return callback(err); + } else if ((doc == null)) { + return callback(new Errors.NotFoundError(`No such doc: ${doc_id} in project ${project_id}`)); + } else if ((doc != null ? doc.inS3 : undefined)) { + return DocArchive.unarchiveDoc(project_id, doc_id, function(err){ + if (err != null) { + logger.err({err, project_id, doc_id}, "error unarchiving doc"); + return callback(err); + } + return DocManager._getDoc(project_id, doc_id, filter, callback); + }); + } else { + if (filter.version) { + return MongoManager.getDocVersion(doc_id, function(error, version) { + if (error != null) { return callback(error); } + doc.version = version; + return callback(err, doc); + }); + } else { + return callback(err, doc); + } + } + }); + }, - checkDocExists: (project_id, doc_id, callback = (err, exists)->)-> - DocManager._getDoc project_id, doc_id, {_id:1, inS3:true}, (err, doc)-> - if err? - return callback(err) - callback(err, doc?) + checkDocExists(project_id, doc_id, callback){ + if (callback == null) { callback = function(err, exists){}; } + return DocManager._getDoc(project_id, doc_id, {_id:1, inS3:true}, function(err, doc){ + if (err != null) { + return callback(err); + } + return callback(err, (doc != null)); + }); + }, - getFullDoc: (project_id, doc_id, callback = (err, doc)->)-> - DocManager._getDoc project_id, doc_id, {lines: true, rev: true, deleted: true, version: true, ranges: true, inS3:true}, (err, doc)-> - if err? - return callback(err) - callback(err, doc) + getFullDoc(project_id, doc_id, callback){ + if (callback == null) { callback = function(err, doc){}; } + return DocManager._getDoc(project_id, doc_id, {lines: true, rev: true, deleted: true, version: true, ranges: true, inS3:true}, function(err, doc){ + if (err != null) { + return callback(err); + } + return callback(err, doc); + }); + }, - getDocLines: (project_id, doc_id, callback = (err, doc)->)-> - DocManager._getDoc project_id, doc_id, {lines:true, inS3:true}, (err, doc)-> - if err? - return callback(err) - callback(err, doc) + getDocLines(project_id, doc_id, callback){ + if (callback == null) { callback = function(err, doc){}; } + return DocManager._getDoc(project_id, doc_id, {lines:true, inS3:true}, function(err, doc){ + if (err != null) { + return callback(err); + } + return callback(err, doc); + }); + }, - getAllNonDeletedDocs: (project_id, filter, callback = (error, docs) ->) -> - DocArchive.unArchiveAllDocs project_id, (error) -> - if error? - return callback(error) - MongoManager.getProjectsDocs project_id, {include_deleted: false}, filter, (error, docs) -> - if err? - return callback(error) - else if !docs? - return callback new Errors.NotFoundError("No docs for project #{project_id}") - else - return callback(null, docs) + getAllNonDeletedDocs(project_id, filter, callback) { + if (callback == null) { callback = function(error, docs) {}; } + return DocArchive.unArchiveAllDocs(project_id, function(error) { + if (error != null) { + return callback(error); + } + return MongoManager.getProjectsDocs(project_id, {include_deleted: false}, filter, function(error, docs) { + if (typeof err !== 'undefined' && err !== null) { + return callback(error); + } else if ((docs == null)) { + return callback(new Errors.NotFoundError(`No docs for project ${project_id}`)); + } else { + return callback(null, docs); + } + }); + }); + }, - updateDoc: (project_id, doc_id, lines, version, ranges, callback = (error, modified, rev) ->) -> - if !lines? or !version? or !ranges? - return callback(new Error("no lines, version or ranges provided")) + updateDoc(project_id, doc_id, lines, version, ranges, callback) { + if (callback == null) { callback = function(error, modified, rev) {}; } + if ((lines == null) || (version == null) || (ranges == null)) { + return callback(new Error("no lines, version or ranges provided")); + } - DocManager._getDoc project_id, doc_id, {version: true, rev: true, lines: true, version: true, ranges: true, inS3:true}, (err, doc)-> - if err? and !(err instanceof Errors.NotFoundError) - logger.err project_id: project_id, doc_id: doc_id, err:err, "error getting document for update" - return callback(err) + return DocManager._getDoc(project_id, doc_id, {version: true, rev: true, lines: true, version: true, ranges: true, inS3:true}, function(err, doc){ + let updateLines, updateRanges, updateVersion; + if ((err != null) && !(err instanceof Errors.NotFoundError)) { + logger.err({project_id, doc_id, err}, "error getting document for update"); + return callback(err); + } - ranges = RangeManager.jsonRangesToMongo(ranges) + ranges = RangeManager.jsonRangesToMongo(ranges); - if !doc? - # If the document doesn't exist, we'll make sure to create/update all parts of it. - updateLines = true - updateVersion = true - updateRanges = true - else - updateLines = not _.isEqual(doc.lines, lines) - updateVersion = (doc.version != version) - updateRanges = RangeManager.shouldUpdateRanges(doc.ranges, ranges) + if ((doc == null)) { + // If the document doesn't exist, we'll make sure to create/update all parts of it. + updateLines = true; + updateVersion = true; + updateRanges = true; + } else { + updateLines = !_.isEqual(doc.lines, lines); + updateVersion = (doc.version !== version); + updateRanges = RangeManager.shouldUpdateRanges(doc.ranges, ranges); + } - modified = false - rev = doc?.rev || 0 + let modified = false; + let rev = (doc != null ? doc.rev : undefined) || 0; - updateLinesAndRangesIfNeeded = (cb) -> - if updateLines or updateRanges - update = {} - if updateLines - update.lines = lines - if updateRanges - update.ranges = ranges - logger.log { project_id, doc_id }, "updating doc lines and ranges" + const updateLinesAndRangesIfNeeded = function(cb) { + if (updateLines || updateRanges) { + const update = {}; + if (updateLines) { + update.lines = lines; + } + if (updateRanges) { + update.ranges = ranges; + } + logger.log({ project_id, doc_id }, "updating doc lines and ranges"); - modified = true - rev += 1 # rev will be incremented in mongo by MongoManager.upsertIntoDocCollection - MongoManager.upsertIntoDocCollection project_id, doc_id, update, cb - else - logger.log { project_id, doc_id, }, "doc lines have not changed - not updating" - cb() + modified = true; + rev += 1; // rev will be incremented in mongo by MongoManager.upsertIntoDocCollection + return MongoManager.upsertIntoDocCollection(project_id, doc_id, update, cb); + } else { + logger.log({ project_id, doc_id, }, "doc lines have not changed - not updating"); + return cb(); + } + }; - updateVersionIfNeeded = (cb) -> - if updateVersion - logger.log { project_id, doc_id, oldVersion: doc?.version, newVersion: version }, "updating doc version" - modified = true - MongoManager.setDocVersion doc_id, version, cb - else - logger.log { project_id, doc_id, version }, "doc version has not changed - not updating" - cb() + const updateVersionIfNeeded = function(cb) { + if (updateVersion) { + logger.log({ project_id, doc_id, oldVersion: (doc != null ? doc.version : undefined), newVersion: version }, "updating doc version"); + modified = true; + return MongoManager.setDocVersion(doc_id, version, cb); + } else { + logger.log({ project_id, doc_id, version }, "doc version has not changed - not updating"); + return cb(); + } + }; - updateLinesAndRangesIfNeeded (error) -> - return callback(error) if error? - updateVersionIfNeeded (error) -> - return callback(error) if error? - callback null, modified, rev + return updateLinesAndRangesIfNeeded(function(error) { + if (error != null) { return callback(error); } + return updateVersionIfNeeded(function(error) { + if (error != null) { return callback(error); } + return callback(null, modified, rev); + }); + }); + }); + }, - deleteDoc: (project_id, doc_id, callback = (error) ->) -> - DocManager.checkDocExists project_id, doc_id, (error, exists) -> - return callback(error) if error? - return callback new Errors.NotFoundError("No such project/doc to delete: #{project_id}/#{doc_id}") if !exists - MongoManager.markDocAsDeleted project_id, doc_id, callback + deleteDoc(project_id, doc_id, callback) { + if (callback == null) { callback = function(error) {}; } + return DocManager.checkDocExists(project_id, doc_id, function(error, exists) { + if (error != null) { return callback(error); } + if (!exists) { return callback(new Errors.NotFoundError(`No such project/doc to delete: ${project_id}/${doc_id}`)); } + return MongoManager.markDocAsDeleted(project_id, doc_id, callback); + }); + } +}); diff --git a/services/docstore/app/coffee/Errors.js b/services/docstore/app/coffee/Errors.js index 4a29822efc..1345cc0f86 100644 --- a/services/docstore/app/coffee/Errors.js +++ b/services/docstore/app/coffee/Errors.js @@ -1,10 +1,12 @@ -NotFoundError = (message) -> - error = new Error(message) - error.name = "NotFoundError" - error.__proto__ = NotFoundError.prototype - return error -NotFoundError.prototype.__proto__ = Error.prototype +let Errors; +var NotFoundError = function(message) { + const error = new Error(message); + error.name = "NotFoundError"; + error.__proto__ = NotFoundError.prototype; + return error; +}; +NotFoundError.prototype.__proto__ = Error.prototype; -module.exports = Errors = - NotFoundError: NotFoundError +module.exports = (Errors = + {NotFoundError}); diff --git a/services/docstore/app/coffee/HealthChecker.js b/services/docstore/app/coffee/HealthChecker.js index 4280f8aa58..1da8c770d0 100644 --- a/services/docstore/app/coffee/HealthChecker.js +++ b/services/docstore/app/coffee/HealthChecker.js @@ -1,44 +1,59 @@ -{db, ObjectId} = require "./mongojs" -request = require("request") -async = require("async") -_ = require("underscore") -crypto = require("crypto") -settings = require("settings-sharelatex") -port = settings.internal.docstore.port -logger = require "logger-sharelatex" +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS207: Consider shorter variations of null checks + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +const {db, ObjectId} = require("./mongojs"); +const request = require("request"); +const async = require("async"); +const _ = require("underscore"); +const crypto = require("crypto"); +const settings = require("settings-sharelatex"); +const { + port +} = settings.internal.docstore; +const logger = require("logger-sharelatex"); -module.exports = - check : (callback)-> - doc_id = ObjectId() - project_id = ObjectId(settings.docstore.healthCheck.project_id) - url = "http://localhost:#{port}/project/#{project_id}/doc/#{doc_id}" - lines = ["smoke test - delete me", "#{crypto.randomBytes(32).toString("hex")}"] - getOpts = -> {url:url, timeout:3000} - logger.log lines:lines, url:url, doc_id:doc_id, project_id:project_id, "running health check" - jobs = [ - (cb)-> - opts = getOpts() - opts.json = {lines: lines, version: 42, ranges: {}} - request.post(opts, cb) - (cb)-> - opts = getOpts() - opts.json = true - request.get opts, (err, res, body)-> - if err? - logger.err err:err, "docstore returned a error in health check get" - cb(err) - else if !res? - cb("no response from docstore with get check") - else if res?.statusCode != 200 - cb("status code not 200, its #{res.statusCode}") - else if _.isEqual(body?.lines, lines) and body?._id == doc_id.toString() - cb() - else - cb("health check lines not equal #{body.lines} != #{lines}") - (cb)-> - db.docs.remove {_id: doc_id, project_id: project_id}, cb - (cb)-> - db.docOps.remove {doc_id: doc_id}, cb - ] - async.series jobs, callback +module.exports = { + check(callback){ + const doc_id = ObjectId(); + const project_id = ObjectId(settings.docstore.healthCheck.project_id); + const url = `http://localhost:${port}/project/${project_id}/doc/${doc_id}`; + const lines = ["smoke test - delete me", `${crypto.randomBytes(32).toString("hex")}`]; + const getOpts = () => ({ + url, + timeout:3000 + }); + logger.log({lines, url, doc_id, project_id}, "running health check"); + const jobs = [ + function(cb){ + const opts = getOpts(); + opts.json = {lines, version: 42, ranges: {}}; + return request.post(opts, cb); + }, + function(cb){ + const opts = getOpts(); + opts.json = true; + return request.get(opts, function(err, res, body){ + if (err != null) { + logger.err({err}, "docstore returned a error in health check get"); + return cb(err); + } else if ((res == null)) { + return cb("no response from docstore with get check"); + } else if ((res != null ? res.statusCode : undefined) !== 200) { + return cb(`status code not 200, its ${res.statusCode}`); + } else if (_.isEqual(body != null ? body.lines : undefined, lines) && ((body != null ? body._id : undefined) === doc_id.toString())) { + return cb(); + } else { + return cb(`health check lines not equal ${body.lines} != ${lines}`); + } + }); + }, + cb => db.docs.remove({_id: doc_id, project_id}, cb), + cb => db.docOps.remove({doc_id}, cb) + ]; + return async.series(jobs, callback); + } +}; diff --git a/services/docstore/app/coffee/HttpController.js b/services/docstore/app/coffee/HttpController.js index cec535e1cd..3d87086a0d 100644 --- a/services/docstore/app/coffee/HttpController.js +++ b/services/docstore/app/coffee/HttpController.js @@ -1,144 +1,224 @@ -DocManager = require "./DocManager" -logger = require "logger-sharelatex" -DocArchive = require "./DocArchiveManager" -HealthChecker = require "./HealthChecker" -Settings = require "settings-sharelatex" +/* + * decaffeinate suggestions: + * DS101: Remove unnecessary use of Array.from + * DS102: Remove unnecessary code created because of implicit returns + * DS207: Consider shorter variations of null checks + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +let HttpController; +const DocManager = require("./DocManager"); +const logger = require("logger-sharelatex"); +const DocArchive = require("./DocArchiveManager"); +const HealthChecker = require("./HealthChecker"); +const Settings = require("settings-sharelatex"); -module.exports = HttpController = - getDoc: (req, res, next = (error) ->) -> - project_id = req.params.project_id - doc_id = req.params.doc_id - include_deleted = req.query?.include_deleted == "true" - logger.log project_id: project_id, doc_id: doc_id, "getting doc" - DocManager.getFullDoc project_id, doc_id, (error, doc) -> - return next(error) if error? - logger.log {doc_id, project_id}, "got doc" - if !doc? - res.send 404 - else if doc.deleted && !include_deleted - res.send 404 - else - res.json HttpController._buildDocView(doc) - - getRawDoc: (req, res, next = (error)->)-> - project_id = req.params.project_id - doc_id = req.params.doc_id - logger.log project_id: project_id, doc_id: doc_id, "getting raw doc" - DocManager.getDocLines project_id, doc_id, (error, doc) -> - return next(error) if error? - if !doc? - res.send 404 - else - res.setHeader('content-type', 'text/plain') - res.send HttpController._buildRawDocView(doc) - - getAllDocs: (req, res, next = (error) ->) -> - project_id = req.params.project_id - logger.log project_id: project_id, "getting all docs" - DocManager.getAllNonDeletedDocs project_id, {lines: true, rev: true}, (error, docs = []) -> - return next(error) if error? - res.json HttpController._buildDocsArrayView(project_id, docs) - - getAllRanges: (req, res, next = (error) ->) -> - project_id = req.params.project_id - logger.log {project_id}, "getting all ranges" - DocManager.getAllNonDeletedDocs project_id, {ranges: true}, (error, docs = []) -> - return next(error) if error? - res.json HttpController._buildDocsArrayView(project_id, docs) - - updateDoc: (req, res, next = (error) ->) -> - project_id = req.params.project_id - doc_id = req.params.doc_id - lines = req.body?.lines - version = req.body?.version - ranges = req.body?.ranges - - if !lines? or lines not instanceof Array - logger.error project_id: project_id, doc_id: doc_id, "no doc lines provided" - res.send 400 # Bad Request - return - - if !version? or typeof version is not "number" - logger.error project_id: project_id, doc_id: doc_id, "no doc version provided" - res.send 400 # Bad Request - return - - if !ranges? - logger.error project_id: project_id, doc_id: doc_id, "no doc ranges provided" - res.send 400 # Bad Request - return - - bodyLength = lines.reduce( - (len, line) => line.length + len - 0 - ) - if bodyLength > Settings.max_doc_length - logger.error project_id: project_id, doc_id: doc_id, bodyLength: bodyLength, "document body too large" - res.status(413).send("document body too large") - return - - logger.log project_id: project_id, doc_id: doc_id, "got http request to update doc" - DocManager.updateDoc project_id, doc_id, lines, version, ranges, (error, modified, rev) -> - return next(error) if error? - res.json { - modified: modified - rev: rev +module.exports = (HttpController = { + getDoc(req, res, next) { + if (next == null) { next = function(error) {}; } + const { + project_id + } = req.params; + const { + doc_id + } = req.params; + const include_deleted = (req.query != null ? req.query.include_deleted : undefined) === "true"; + logger.log({project_id, doc_id}, "getting doc"); + return DocManager.getFullDoc(project_id, doc_id, function(error, doc) { + if (error != null) { return next(error); } + logger.log({doc_id, project_id}, "got doc"); + if ((doc == null)) { + return res.send(404); + } else if (doc.deleted && !include_deleted) { + return res.send(404); + } else { + return res.json(HttpController._buildDocView(doc)); } + }); + }, - deleteDoc: (req, res, next = (error) ->) -> - project_id = req.params.project_id - doc_id = req.params.doc_id - logger.log project_id: project_id, doc_id: doc_id, "deleting doc" - DocManager.deleteDoc project_id, doc_id, (error) -> - return next(error) if error? - res.send 204 + getRawDoc(req, res, next){ + if (next == null) { next = function(error){}; } + const { + project_id + } = req.params; + const { + doc_id + } = req.params; + logger.log({project_id, doc_id}, "getting raw doc"); + return DocManager.getDocLines(project_id, doc_id, function(error, doc) { + if (error != null) { return next(error); } + if ((doc == null)) { + return res.send(404); + } else { + res.setHeader('content-type', 'text/plain'); + return res.send(HttpController._buildRawDocView(doc)); + } + }); + }, - _buildDocView: (doc) -> - doc_view = { _id: doc._id?.toString() } - for attribute in ["lines", "rev", "version", "ranges", "deleted"] - if doc[attribute]? - doc_view[attribute] = doc[attribute] - return doc_view - - _buildRawDocView: (doc)-> - return (doc?.lines or []).join("\n") + getAllDocs(req, res, next) { + if (next == null) { next = function(error) {}; } + const { + project_id + } = req.params; + logger.log({project_id}, "getting all docs"); + return DocManager.getAllNonDeletedDocs(project_id, {lines: true, rev: true}, function(error, docs) { + if (docs == null) { docs = []; } + if (error != null) { return next(error); } + return res.json(HttpController._buildDocsArrayView(project_id, docs)); + }); + }, - _buildDocsArrayView: (project_id, docs) -> - docViews = [] - for doc in docs - if doc? # There can end up being null docs for some reason :( (probably a race condition) - docViews.push HttpController._buildDocView(doc) - else - logger.error err: new Error("null doc"), project_id: project_id, "encountered null doc" - return docViews + getAllRanges(req, res, next) { + if (next == null) { next = function(error) {}; } + const { + project_id + } = req.params; + logger.log({project_id}, "getting all ranges"); + return DocManager.getAllNonDeletedDocs(project_id, {ranges: true}, function(error, docs) { + if (docs == null) { docs = []; } + if (error != null) { return next(error); } + return res.json(HttpController._buildDocsArrayView(project_id, docs)); + }); + }, - archiveAllDocs: (req, res, next = (error) ->) -> - project_id = req.params.project_id - logger.log project_id: project_id, "archiving all docs" - DocArchive.archiveAllDocs project_id, (error) -> - return next(error) if error? - res.send 204 + updateDoc(req, res, next) { + if (next == null) { next = function(error) {}; } + const { + project_id + } = req.params; + const { + doc_id + } = req.params; + const lines = req.body != null ? req.body.lines : undefined; + const version = req.body != null ? req.body.version : undefined; + const ranges = req.body != null ? req.body.ranges : undefined; - unArchiveAllDocs: (req, res, next = (error) ->) -> - project_id = req.params.project_id - logger.log project_id: project_id, "unarchiving all docs" - DocArchive.unArchiveAllDocs project_id, (error) -> - return next(error) if error? - res.send 200 + if ((lines == null) || !(lines instanceof Array)) { + logger.error({project_id, doc_id}, "no doc lines provided"); + res.send(400); // Bad Request + return; + } + + if ((version == null) || (typeof version === !"number")) { + logger.error({project_id, doc_id}, "no doc version provided"); + res.send(400); // Bad Request + return; + } + + if ((ranges == null)) { + logger.error({project_id, doc_id}, "no doc ranges provided"); + res.send(400); // Bad Request + return; + } - destroyAllDocs: (req, res, next = (error) ->) -> - project_id = req.params.project_id - logger.log project_id: project_id, "destroying all docs" - DocArchive.destroyAllDocs project_id, (error) -> - return next(error) if error? - res.send 204 + const bodyLength = lines.reduce( + (len, line) => line.length + len, + 0 + ); + if (bodyLength > Settings.max_doc_length) { + logger.error({project_id, doc_id, bodyLength}, "document body too large"); + res.status(413).send("document body too large"); + return; + } - healthCheck: (req, res)-> - HealthChecker.check (err)-> - if err? - logger.err err:err, "error performing health check" - res.send 500 - else - res.send 200 + logger.log({project_id, doc_id}, "got http request to update doc"); + return DocManager.updateDoc(project_id, doc_id, lines, version, ranges, function(error, modified, rev) { + if (error != null) { return next(error); } + return res.json({ + modified, + rev + }); + }); + }, + + deleteDoc(req, res, next) { + if (next == null) { next = function(error) {}; } + const { + project_id + } = req.params; + const { + doc_id + } = req.params; + logger.log({project_id, doc_id}, "deleting doc"); + return DocManager.deleteDoc(project_id, doc_id, function(error) { + if (error != null) { return next(error); } + return res.send(204); + }); + }, + + _buildDocView(doc) { + const doc_view = { _id: (doc._id != null ? doc._id.toString() : undefined) }; + for (let attribute of ["lines", "rev", "version", "ranges", "deleted"]) { + if (doc[attribute] != null) { + doc_view[attribute] = doc[attribute]; + } + } + return doc_view; + }, + + _buildRawDocView(doc){ + return ((doc != null ? doc.lines : undefined) || []).join("\n"); + }, + + _buildDocsArrayView(project_id, docs) { + const docViews = []; + for (let doc of Array.from(docs)) { + if (doc != null) { // There can end up being null docs for some reason :( (probably a race condition) + docViews.push(HttpController._buildDocView(doc)); + } else { + logger.error({err: new Error("null doc"), project_id}, "encountered null doc"); + } + } + return docViews; + }, + + archiveAllDocs(req, res, next) { + if (next == null) { next = function(error) {}; } + const { + project_id + } = req.params; + logger.log({project_id}, "archiving all docs"); + return DocArchive.archiveAllDocs(project_id, function(error) { + if (error != null) { return next(error); } + return res.send(204); + }); + }, + + unArchiveAllDocs(req, res, next) { + if (next == null) { next = function(error) {}; } + const { + project_id + } = req.params; + logger.log({project_id}, "unarchiving all docs"); + return DocArchive.unArchiveAllDocs(project_id, function(error) { + if (error != null) { return next(error); } + return res.send(200); + }); + }, + + destroyAllDocs(req, res, next) { + if (next == null) { next = function(error) {}; } + const { + project_id + } = req.params; + logger.log({project_id}, "destroying all docs"); + return DocArchive.destroyAllDocs(project_id, function(error) { + if (error != null) { return next(error); } + return res.send(204); + }); + }, + + healthCheck(req, res){ + return HealthChecker.check(function(err){ + if (err != null) { + logger.err({err}, "error performing health check"); + return res.send(500); + } else { + return res.send(200); + } + }); + } +}); diff --git a/services/docstore/app/coffee/MongoManager.js b/services/docstore/app/coffee/MongoManager.js index 3bd9eb34c5..0fc304b79f 100644 --- a/services/docstore/app/coffee/MongoManager.js +++ b/services/docstore/app/coffee/MongoManager.js @@ -1,85 +1,118 @@ -{db, ObjectId} = require "./mongojs" -logger = require 'logger-sharelatex' -metrics = require 'metrics-sharelatex' +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS207: Consider shorter variations of null checks + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +let MongoManager; +const {db, ObjectId} = require("./mongojs"); +const logger = require('logger-sharelatex'); +const metrics = require('metrics-sharelatex'); -module.exports = MongoManager = +module.exports = (MongoManager = { - findDoc: (project_id, doc_id, filter, callback = (error, doc) ->) -> - db.docs.find {_id: ObjectId(doc_id.toString()), project_id: ObjectId(project_id.toString())}, filter, (error, docs = []) -> - callback error, docs[0] + findDoc(project_id, doc_id, filter, callback) { + if (callback == null) { callback = function(error, doc) {}; } + return db.docs.find({_id: ObjectId(doc_id.toString()), project_id: ObjectId(project_id.toString())}, filter, function(error, docs) { + if (docs == null) { docs = []; } + return callback(error, docs[0]); + }); + }, - getProjectsDocs: (project_id, options = {include_deleted: true}, filter, callback)-> - query = {project_id: ObjectId(project_id.toString())} - if !options.include_deleted - query.deleted = { $ne: true } - db.docs.find query, filter, callback + getProjectsDocs(project_id, options, filter, callback){ + if (options == null) { options = {include_deleted: true}; } + const query = {project_id: ObjectId(project_id.toString())}; + if (!options.include_deleted) { + query.deleted = { $ne: true }; + } + return db.docs.find(query, filter, callback); + }, - getArchivedProjectDocs: (project_id, callback)-> - query = - project_id: ObjectId(project_id.toString()) + getArchivedProjectDocs(project_id, callback){ + const query = { + project_id: ObjectId(project_id.toString()), inS3: true - db.docs.find query, {}, callback + }; + return db.docs.find(query, {}, callback); + }, - upsertIntoDocCollection: (project_id, doc_id, updates, callback)-> - update = - $set: updates - $inc: + upsertIntoDocCollection(project_id, doc_id, updates, callback){ + const update = { + $set: updates, + $inc: { rev: 1 - $unset: + }, + $unset: { inS3: true - update.$set["project_id"] = ObjectId(project_id) - db.docs.update _id: ObjectId(doc_id), update, {upsert: true}, callback + } + }; + update.$set["project_id"] = ObjectId(project_id); + return db.docs.update({_id: ObjectId(doc_id)}, update, {upsert: true}, callback); + }, - markDocAsDeleted: (project_id, doc_id, callback)-> - db.docs.update { + markDocAsDeleted(project_id, doc_id, callback){ + return db.docs.update({ _id: ObjectId(doc_id), project_id: ObjectId(project_id) }, { $set: { deleted: true } - }, callback + }, callback); + }, - markDocAsArchived: (doc_id, rev, callback)-> - update = - $set: {} + markDocAsArchived(doc_id, rev, callback){ + const update = { + $set: {}, $unset: {} - update.$set["inS3"] = true - update.$unset["lines"] = true - update.$unset["ranges"] = true - query = - _id: doc_id - rev: rev - db.docs.update query, update, (err)-> - callback(err) + }; + update.$set["inS3"] = true; + update.$unset["lines"] = true; + update.$unset["ranges"] = true; + const query = { + _id: doc_id, + rev + }; + return db.docs.update(query, update, err => callback(err)); + }, - getDocVersion: (doc_id, callback = (error, version) ->) -> - db.docOps.find { + getDocVersion(doc_id, callback) { + if (callback == null) { callback = function(error, version) {}; } + return db.docOps.find({ doc_id: ObjectId(doc_id) }, { version: 1 - }, (error, docs) -> - return callback(error) if error? - if docs.length < 1 or !docs[0].version? - return callback null, 0 - else - return callback null, docs[0].version + }, function(error, docs) { + if (error != null) { return callback(error); } + if ((docs.length < 1) || (docs[0].version == null)) { + return callback(null, 0); + } else { + return callback(null, docs[0].version); + } + }); + }, - setDocVersion: (doc_id, version, callback = (error) ->) -> - db.docOps.update { + setDocVersion(doc_id, version, callback) { + if (callback == null) { callback = function(error) {}; } + return db.docOps.update({ doc_id: ObjectId(doc_id) }, { - $set: version: version + $set: { version + } }, { upsert: true - }, callback + }, callback); + }, - destroyDoc: (doc_id, callback) -> - db.docs.remove { + destroyDoc(doc_id, callback) { + return db.docs.remove({ _id: ObjectId(doc_id) - }, (err) -> - return callback(err) if err? - db.docOps.remove { + }, function(err) { + if (err != null) { return callback(err); } + return db.docOps.remove({ doc_id: ObjectId(doc_id) - }, callback + }, callback); + }); + } +}); [ 'findDoc', @@ -89,5 +122,4 @@ module.exports = MongoManager = 'markDocAsArchived', 'getDocVersion', 'setDocVersion' -].map (method) -> - metrics.timeAsyncMethod(MongoManager, method, 'mongo.MongoManager', logger) +].map(method => metrics.timeAsyncMethod(MongoManager, method, 'mongo.MongoManager', logger)); diff --git a/services/docstore/app/coffee/RangeManager.js b/services/docstore/app/coffee/RangeManager.js index 4867ffbe19..6973ebd259 100644 --- a/services/docstore/app/coffee/RangeManager.js +++ b/services/docstore/app/coffee/RangeManager.js @@ -1,40 +1,61 @@ -_ = require "underscore" -{ObjectId} = require("./mongojs") +/* + * decaffeinate suggestions: + * DS101: Remove unnecessary use of Array.from + * DS102: Remove unnecessary code created because of implicit returns + * DS207: Consider shorter variations of null checks + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +let RangeManager; +const _ = require("underscore"); +const {ObjectId} = require("./mongojs"); -module.exports = RangeManager = - shouldUpdateRanges: (doc_ranges, incoming_ranges) -> - if !incoming_ranges? - throw new Error("expected incoming_ranges") +module.exports = (RangeManager = { + shouldUpdateRanges(doc_ranges, incoming_ranges) { + if ((incoming_ranges == null)) { + throw new Error("expected incoming_ranges"); + } - # If the ranges are empty, we don't store them in the DB, so set - # doc_ranges to an empty object as default, since this is was the - # incoming_ranges will be for an empty range set. - if !doc_ranges? - doc_ranges = {} + // If the ranges are empty, we don't store them in the DB, so set + // doc_ranges to an empty object as default, since this is was the + // incoming_ranges will be for an empty range set. + if ((doc_ranges == null)) { + doc_ranges = {}; + } - return not _.isEqual(doc_ranges, incoming_ranges) + return !_.isEqual(doc_ranges, incoming_ranges); + }, - jsonRangesToMongo: (ranges) -> - return null if !ranges? + jsonRangesToMongo(ranges) { + if ((ranges == null)) { return null; } - updateMetadata = (metadata) -> - if metadata?.ts? - metadata.ts = new Date(metadata.ts) - if metadata?.user_id? - metadata.user_id = RangeManager._safeObjectId(metadata.user_id) + const updateMetadata = function(metadata) { + if ((metadata != null ? metadata.ts : undefined) != null) { + metadata.ts = new Date(metadata.ts); + } + if ((metadata != null ? metadata.user_id : undefined) != null) { + return metadata.user_id = RangeManager._safeObjectId(metadata.user_id); + } + }; - for change in ranges.changes or [] - change.id = RangeManager._safeObjectId(change.id) - updateMetadata(change.metadata) - for comment in ranges.comments or [] - comment.id = RangeManager._safeObjectId(comment.id) - if comment.op?.t? - comment.op.t = RangeManager._safeObjectId(comment.op.t) - updateMetadata(comment.metadata) - return ranges + for (let change of Array.from(ranges.changes || [])) { + change.id = RangeManager._safeObjectId(change.id); + updateMetadata(change.metadata); + } + for (let comment of Array.from(ranges.comments || [])) { + comment.id = RangeManager._safeObjectId(comment.id); + if ((comment.op != null ? comment.op.t : undefined) != null) { + comment.op.t = RangeManager._safeObjectId(comment.op.t); + } + updateMetadata(comment.metadata); + } + return ranges; + }, - _safeObjectId: (data) -> - try - return ObjectId(data) - catch error - return data \ No newline at end of file + _safeObjectId(data) { + try { + return ObjectId(data); + } catch (error) { + return data; + } + } +}); \ No newline at end of file diff --git a/services/docstore/app/coffee/mongojs.js b/services/docstore/app/coffee/mongojs.js index 0153c3cfcd..fd0d6cde8b 100644 --- a/services/docstore/app/coffee/mongojs.js +++ b/services/docstore/app/coffee/mongojs.js @@ -1,7 +1,8 @@ -Settings = require "settings-sharelatex" -mongojs = require "mongojs" -db = mongojs(Settings.mongo.url, ["docs", "docOps"]) -module.exports = - db: db +const Settings = require("settings-sharelatex"); +const mongojs = require("mongojs"); +const db = mongojs(Settings.mongo.url, ["docs", "docOps"]); +module.exports = { + db, ObjectId: mongojs.ObjectId +}; From d31a747c72c70726ce9776639a032b4f5d0ad9f0 Mon Sep 17 00:00:00 2001 From: decaffeinate Date: Sun, 16 Feb 2020 14:01:47 +0000 Subject: [PATCH 06/27] decaffeinate: Run post-processing cleanups on DocArchiveManager.coffee and 7 other files --- services/docstore/app/coffee/DocArchiveManager.js | 7 +++++++ services/docstore/app/coffee/DocManager.js | 9 +++++++++ services/docstore/app/coffee/Errors.js | 6 ++++++ services/docstore/app/coffee/HealthChecker.js | 6 ++++++ services/docstore/app/coffee/HttpController.js | 11 +++++++++-- services/docstore/app/coffee/MongoManager.js | 14 ++++++++++---- services/docstore/app/coffee/RangeManager.js | 10 ++++++++-- services/docstore/app/coffee/mongojs.js | 2 ++ 8 files changed, 57 insertions(+), 8 deletions(-) diff --git a/services/docstore/app/coffee/DocArchiveManager.js b/services/docstore/app/coffee/DocArchiveManager.js index e3c048558e..636d8b155b 100644 --- a/services/docstore/app/coffee/DocArchiveManager.js +++ b/services/docstore/app/coffee/DocArchiveManager.js @@ -1,3 +1,10 @@ +/* eslint-disable + camelcase, + handle-callback-err, + no-useless-escape, +*/ +// TODO: This file was created by bulk-decaffeinate. +// Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS102: Remove unnecessary code created because of implicit returns diff --git a/services/docstore/app/coffee/DocManager.js b/services/docstore/app/coffee/DocManager.js index 8bb86d8eb3..bddb1ee937 100644 --- a/services/docstore/app/coffee/DocManager.js +++ b/services/docstore/app/coffee/DocManager.js @@ -1,3 +1,12 @@ +/* eslint-disable + camelcase, + handle-callback-err, + no-dupe-keys, + no-undef, + standard/no-callback-literal, +*/ +// TODO: This file was created by bulk-decaffeinate. +// Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS102: Remove unnecessary code created because of implicit returns diff --git a/services/docstore/app/coffee/Errors.js b/services/docstore/app/coffee/Errors.js index 1345cc0f86..a000b8f1f4 100644 --- a/services/docstore/app/coffee/Errors.js +++ b/services/docstore/app/coffee/Errors.js @@ -1,3 +1,9 @@ +/* eslint-disable + no-proto, + no-unused-vars, +*/ +// TODO: This file was created by bulk-decaffeinate. +// Fix any style issues and re-enable lint. let Errors; var NotFoundError = function(message) { const error = new Error(message); diff --git a/services/docstore/app/coffee/HealthChecker.js b/services/docstore/app/coffee/HealthChecker.js index 1da8c770d0..143e797f4e 100644 --- a/services/docstore/app/coffee/HealthChecker.js +++ b/services/docstore/app/coffee/HealthChecker.js @@ -1,3 +1,9 @@ +/* eslint-disable + camelcase, + standard/no-callback-literal, +*/ +// TODO: This file was created by bulk-decaffeinate. +// Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS102: Remove unnecessary code created because of implicit returns diff --git a/services/docstore/app/coffee/HttpController.js b/services/docstore/app/coffee/HttpController.js index 3d87086a0d..7f6eb9e728 100644 --- a/services/docstore/app/coffee/HttpController.js +++ b/services/docstore/app/coffee/HttpController.js @@ -1,3 +1,10 @@ +/* eslint-disable + camelcase, + handle-callback-err, + valid-typeof, +*/ +// TODO: This file was created by bulk-decaffeinate. +// Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS101: Remove unnecessary use of Array.from @@ -150,7 +157,7 @@ module.exports = (HttpController = { _buildDocView(doc) { const doc_view = { _id: (doc._id != null ? doc._id.toString() : undefined) }; - for (let attribute of ["lines", "rev", "version", "ranges", "deleted"]) { + for (const attribute of ["lines", "rev", "version", "ranges", "deleted"]) { if (doc[attribute] != null) { doc_view[attribute] = doc[attribute]; } @@ -164,7 +171,7 @@ module.exports = (HttpController = { _buildDocsArrayView(project_id, docs) { const docViews = []; - for (let doc of Array.from(docs)) { + for (const doc of Array.from(docs)) { if (doc != null) { // There can end up being null docs for some reason :( (probably a race condition) docViews.push(HttpController._buildDocView(doc)); } else { diff --git a/services/docstore/app/coffee/MongoManager.js b/services/docstore/app/coffee/MongoManager.js index 0fc304b79f..27918267f9 100644 --- a/services/docstore/app/coffee/MongoManager.js +++ b/services/docstore/app/coffee/MongoManager.js @@ -1,3 +1,9 @@ +/* eslint-disable + camelcase, + handle-callback-err, +*/ +// TODO: This file was created by bulk-decaffeinate. +// Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS102: Remove unnecessary code created because of implicit returns @@ -46,7 +52,7 @@ module.exports = (MongoManager = { inS3: true } }; - update.$set["project_id"] = ObjectId(project_id); + update.$set.project_id = ObjectId(project_id); return db.docs.update({_id: ObjectId(doc_id)}, update, {upsert: true}, callback); }, @@ -64,9 +70,9 @@ module.exports = (MongoManager = { $set: {}, $unset: {} }; - update.$set["inS3"] = true; - update.$unset["lines"] = true; - update.$unset["ranges"] = true; + update.$set.inS3 = true; + update.$unset.lines = true; + update.$unset.ranges = true; const query = { _id: doc_id, rev diff --git a/services/docstore/app/coffee/RangeManager.js b/services/docstore/app/coffee/RangeManager.js index 6973ebd259..cee272a8e6 100644 --- a/services/docstore/app/coffee/RangeManager.js +++ b/services/docstore/app/coffee/RangeManager.js @@ -1,3 +1,9 @@ +/* eslint-disable + camelcase, + no-return-assign, +*/ +// TODO: This file was created by bulk-decaffeinate. +// Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS101: Remove unnecessary use of Array.from @@ -37,11 +43,11 @@ module.exports = (RangeManager = { } }; - for (let change of Array.from(ranges.changes || [])) { + for (const change of Array.from(ranges.changes || [])) { change.id = RangeManager._safeObjectId(change.id); updateMetadata(change.metadata); } - for (let comment of Array.from(ranges.comments || [])) { + for (const comment of Array.from(ranges.comments || [])) { comment.id = RangeManager._safeObjectId(comment.id); if ((comment.op != null ? comment.op.t : undefined) != null) { comment.op.t = RangeManager._safeObjectId(comment.op.t); diff --git a/services/docstore/app/coffee/mongojs.js b/services/docstore/app/coffee/mongojs.js index fd0d6cde8b..8000129ae5 100644 --- a/services/docstore/app/coffee/mongojs.js +++ b/services/docstore/app/coffee/mongojs.js @@ -1,3 +1,5 @@ +// TODO: This file was created by bulk-decaffeinate. +// Sanity-check the conversion and remove this comment. const Settings = require("settings-sharelatex"); const mongojs = require("mongojs"); const db = mongojs(Settings.mongo.url, ["docs", "docOps"]); From c1805978c4c14699fe4cc9728746bd2bdfa1ae86 Mon Sep 17 00:00:00 2001 From: Simon Detheridge Date: Sun, 16 Feb 2020 14:02:01 +0000 Subject: [PATCH 07/27] decaffeinate: rename app/coffee dir to app/js --- services/docstore/app/{coffee => js}/DocArchiveManager.js | 0 services/docstore/app/{coffee => js}/DocManager.js | 0 services/docstore/app/{coffee => js}/Errors.js | 0 services/docstore/app/{coffee => js}/HealthChecker.js | 0 services/docstore/app/{coffee => js}/HttpController.js | 0 services/docstore/app/{coffee => js}/MongoManager.js | 0 services/docstore/app/{coffee => js}/RangeManager.js | 0 services/docstore/app/{coffee => js}/mongojs.js | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename services/docstore/app/{coffee => js}/DocArchiveManager.js (100%) rename services/docstore/app/{coffee => js}/DocManager.js (100%) rename services/docstore/app/{coffee => js}/Errors.js (100%) rename services/docstore/app/{coffee => js}/HealthChecker.js (100%) rename services/docstore/app/{coffee => js}/HttpController.js (100%) rename services/docstore/app/{coffee => js}/MongoManager.js (100%) rename services/docstore/app/{coffee => js}/RangeManager.js (100%) rename services/docstore/app/{coffee => js}/mongojs.js (100%) diff --git a/services/docstore/app/coffee/DocArchiveManager.js b/services/docstore/app/js/DocArchiveManager.js similarity index 100% rename from services/docstore/app/coffee/DocArchiveManager.js rename to services/docstore/app/js/DocArchiveManager.js diff --git a/services/docstore/app/coffee/DocManager.js b/services/docstore/app/js/DocManager.js similarity index 100% rename from services/docstore/app/coffee/DocManager.js rename to services/docstore/app/js/DocManager.js diff --git a/services/docstore/app/coffee/Errors.js b/services/docstore/app/js/Errors.js similarity index 100% rename from services/docstore/app/coffee/Errors.js rename to services/docstore/app/js/Errors.js diff --git a/services/docstore/app/coffee/HealthChecker.js b/services/docstore/app/js/HealthChecker.js similarity index 100% rename from services/docstore/app/coffee/HealthChecker.js rename to services/docstore/app/js/HealthChecker.js diff --git a/services/docstore/app/coffee/HttpController.js b/services/docstore/app/js/HttpController.js similarity index 100% rename from services/docstore/app/coffee/HttpController.js rename to services/docstore/app/js/HttpController.js diff --git a/services/docstore/app/coffee/MongoManager.js b/services/docstore/app/js/MongoManager.js similarity index 100% rename from services/docstore/app/coffee/MongoManager.js rename to services/docstore/app/js/MongoManager.js diff --git a/services/docstore/app/coffee/RangeManager.js b/services/docstore/app/js/RangeManager.js similarity index 100% rename from services/docstore/app/coffee/RangeManager.js rename to services/docstore/app/js/RangeManager.js diff --git a/services/docstore/app/coffee/mongojs.js b/services/docstore/app/js/mongojs.js similarity index 100% rename from services/docstore/app/coffee/mongojs.js rename to services/docstore/app/js/mongojs.js From fb931e206c95bf1788534dac5bb9839b6229bf3e Mon Sep 17 00:00:00 2001 From: Simon Detheridge Date: Sun, 16 Feb 2020 14:02:21 +0000 Subject: [PATCH 08/27] prettier: convert app/js decaffeinated files to Prettier format --- services/docstore/app/js/DocArchiveManager.js | 461 ++++++++++-------- services/docstore/app/js/DocManager.js | 426 +++++++++------- services/docstore/app/js/Errors.js | 18 +- services/docstore/app/js/HealthChecker.js | 107 ++-- services/docstore/app/js/HttpController.js | 434 +++++++++-------- services/docstore/app/js/MongoManager.js | 263 +++++----- services/docstore/app/js/RangeManager.js | 104 ++-- services/docstore/app/js/mongojs.js | 13 +- 8 files changed, 1039 insertions(+), 787 deletions(-) diff --git a/services/docstore/app/js/DocArchiveManager.js b/services/docstore/app/js/DocArchiveManager.js index 636d8b155b..af1af21957 100644 --- a/services/docstore/app/js/DocArchiveManager.js +++ b/services/docstore/app/js/DocArchiveManager.js @@ -11,205 +11,282 @@ * DS207: Consider shorter variations of null checks * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -let DocArchive; -const MongoManager = require("./MongoManager"); -const Errors = require("./Errors"); -const logger = require("logger-sharelatex"); -const _ = require("underscore"); -const async = require("async"); -const settings = require("settings-sharelatex"); -const request = require("request"); -const crypto = require("crypto"); -const RangeManager = require("./RangeManager"); -const thirtySeconds = 30 * 1000; +let DocArchive +const MongoManager = require('./MongoManager') +const Errors = require('./Errors') +const logger = require('logger-sharelatex') +const _ = require('underscore') +const async = require('async') +const settings = require('settings-sharelatex') +const request = require('request') +const crypto = require('crypto') +const RangeManager = require('./RangeManager') +const thirtySeconds = 30 * 1000 -module.exports = (DocArchive = { +module.exports = DocArchive = { + archiveAllDocs(project_id, callback) { + if (callback == null) { + callback = function(err, docs) {} + } + return MongoManager.getProjectsDocs( + project_id, + { include_deleted: true }, + { lines: true, ranges: true, rev: true, inS3: true }, + function(err, docs) { + if (err != null) { + return callback(err) + } else if (docs == null) { + return callback( + new Errors.NotFoundError(`No docs for project ${project_id}`) + ) + } + docs = _.filter(docs, doc => doc.inS3 !== true) + const jobs = _.map(docs, doc => cb => + DocArchive.archiveDoc(project_id, doc, cb) + ) + return async.parallelLimit(jobs, 5, callback) + } + ) + }, - archiveAllDocs(project_id, callback) { - if (callback == null) { callback = function(err, docs) {}; } - return MongoManager.getProjectsDocs(project_id, {include_deleted: true}, {lines: true, ranges: true, rev: true, inS3: true}, function(err, docs) { - if (err != null) { - return callback(err); - } else if ((docs == null)) { - return callback(new Errors.NotFoundError(`No docs for project ${project_id}`)); - } - docs = _.filter(docs, doc => doc.inS3 !== true); - const jobs = _.map(docs, doc => cb => DocArchive.archiveDoc(project_id, doc, cb)); - return async.parallelLimit(jobs, 5, callback); - }); - }, + archiveDoc(project_id, doc, callback) { + let options + logger.log({ project_id, doc_id: doc._id }, 'sending doc to s3') + try { + options = DocArchive.buildS3Options(project_id + '/' + doc._id) + } catch (e) { + return callback(e) + } + return DocArchive._mongoDocToS3Doc(doc, function(error, json_doc) { + if (error != null) { + return callback(error) + } + options.body = json_doc + options.headers = { 'Content-Type': 'application/json' } + return request.put(options, function(err, res) { + if (err != null || res.statusCode !== 200) { + logger.err( + { + err, + res, + project_id, + doc_id: doc._id, + statusCode: res != null ? res.statusCode : undefined + }, + 'something went wrong archiving doc in aws' + ) + return callback(new Error('Error in S3 request')) + } + const md5lines = crypto + .createHash('md5') + .update(json_doc, 'utf8') + .digest('hex') + const md5response = res.headers.etag.toString().replace(/\"/g, '') + if (md5lines !== md5response) { + logger.err( + { + responseMD5: md5response, + linesMD5: md5lines, + project_id, + doc_id: doc != null ? doc._id : undefined + }, + 'err in response md5 from s3' + ) + return callback(new Error('Error in S3 md5 response')) + } + return MongoManager.markDocAsArchived(doc._id, doc.rev, function(err) { + if (err != null) { + return callback(err) + } + return callback() + }) + }) + }) + }, + unArchiveAllDocs(project_id, callback) { + if (callback == null) { + callback = function(err) {} + } + return MongoManager.getArchivedProjectDocs(project_id, function(err, docs) { + if (err != null) { + logger.err({ err, project_id }, 'error unarchiving all docs') + return callback(err) + } else if (docs == null) { + return callback( + new Errors.NotFoundError(`No docs for project ${project_id}`) + ) + } + const jobs = _.map( + docs, + doc => + function(cb) { + if (doc.inS3 == null) { + return cb() + } else { + return DocArchive.unarchiveDoc(project_id, doc._id, cb) + } + } + ) + return async.parallelLimit(jobs, 5, callback) + }) + }, - archiveDoc(project_id, doc, callback){ - let options; - logger.log({project_id, doc_id: doc._id}, "sending doc to s3"); - try { - options = DocArchive.buildS3Options(project_id+"/"+doc._id); - } catch (e) { - return callback(e); - } - return DocArchive._mongoDocToS3Doc(doc, function(error, json_doc) { - if (error != null) { return callback(error); } - options.body = json_doc; - options.headers = - {'Content-Type': "application/json"}; - return request.put(options, function(err, res) { - if ((err != null) || (res.statusCode !== 200)) { - logger.err({err, res, project_id, doc_id: doc._id, statusCode: (res != null ? res.statusCode : undefined)}, "something went wrong archiving doc in aws"); - return callback(new Error("Error in S3 request")); - } - const md5lines = crypto.createHash("md5").update(json_doc, "utf8").digest("hex"); - const md5response = res.headers.etag.toString().replace(/\"/g, ''); - if (md5lines !== md5response) { - logger.err({responseMD5:md5response, linesMD5:md5lines, project_id, doc_id: (doc != null ? doc._id : undefined)}, "err in response md5 from s3"); - return callback(new Error("Error in S3 md5 response")); - } - return MongoManager.markDocAsArchived(doc._id, doc.rev, function(err) { - if (err != null) { return callback(err); } - return callback(); - }); - }); - }); - }, + unarchiveDoc(project_id, doc_id, callback) { + let options + logger.log({ project_id, doc_id }, 'getting doc from s3') + try { + options = DocArchive.buildS3Options(project_id + '/' + doc_id) + } catch (e) { + return callback(e) + } + options.json = true + return request.get(options, function(err, res, doc) { + if (err != null || res.statusCode !== 200) { + logger.err( + { err, res, project_id, doc_id }, + 'something went wrong unarchiving doc from aws' + ) + return callback(new Errors.NotFoundError('Error in S3 request')) + } + return DocArchive._s3DocToMongoDoc(doc, function(error, mongo_doc) { + if (error != null) { + return callback(error) + } + return MongoManager.upsertIntoDocCollection( + project_id, + doc_id.toString(), + mongo_doc, + function(err) { + if (err != null) { + return callback(err) + } + logger.log({ project_id, doc_id }, 'deleting doc from s3') + return DocArchive._deleteDocFromS3(project_id, doc_id, callback) + } + ) + }) + }) + }, - unArchiveAllDocs(project_id, callback) { - if (callback == null) { callback = function(err) {}; } - return MongoManager.getArchivedProjectDocs(project_id, function(err, docs) { - if (err != null) { - logger.err({err, project_id}, "error unarchiving all docs"); - return callback(err); - } else if ((docs == null)) { - return callback(new Errors.NotFoundError(`No docs for project ${project_id}`)); - } - const jobs = _.map(docs, doc => (function(cb) { - if ((doc.inS3 == null)) { - return cb(); - } else { - return DocArchive.unarchiveDoc(project_id, doc._id, cb); - } - })); - return async.parallelLimit(jobs, 5, callback); - }); - }, + destroyAllDocs(project_id, callback) { + if (callback == null) { + callback = function(err) {} + } + return MongoManager.getProjectsDocs( + project_id, + { include_deleted: true }, + { _id: 1 }, + function(err, docs) { + if (err != null) { + logger.err({ err, project_id }, "error getting project's docs") + return callback(err) + } else if (docs == null) { + return callback() + } + const jobs = _.map(docs, doc => cb => + DocArchive.destroyDoc(project_id, doc._id, cb) + ) + return async.parallelLimit(jobs, 5, callback) + } + ) + }, - unarchiveDoc(project_id, doc_id, callback){ - let options; - logger.log({project_id, doc_id}, "getting doc from s3"); - try { - options = DocArchive.buildS3Options(project_id+"/"+doc_id); - } catch (e) { - return callback(e); - } - options.json = true; - return request.get(options, function(err, res, doc){ - if ((err != null) || (res.statusCode !== 200)) { - logger.err({err, res, project_id, doc_id}, "something went wrong unarchiving doc from aws"); - return callback(new Errors.NotFoundError("Error in S3 request")); - } - return DocArchive._s3DocToMongoDoc(doc, function(error, mongo_doc) { - if (error != null) { return callback(error); } - return MongoManager.upsertIntoDocCollection(project_id, doc_id.toString(), mongo_doc, function(err) { - if (err != null) { return callback(err); } - logger.log({project_id, doc_id}, "deleting doc from s3"); - return DocArchive._deleteDocFromS3(project_id, doc_id, callback); - }); - }); - }); - }, + destroyDoc(project_id, doc_id, callback) { + logger.log({ project_id, doc_id }, 'removing doc from mongo and s3') + return MongoManager.findDoc(project_id, doc_id, { inS3: 1 }, function( + error, + doc + ) { + if (error != null) { + return callback(error) + } + if (doc == null) { + return callback(new Errors.NotFoundError('Doc not found in Mongo')) + } + if (doc.inS3 === true) { + return DocArchive._deleteDocFromS3(project_id, doc_id, function(err) { + if (err != null) { + return err + } + return MongoManager.destroyDoc(doc_id, callback) + }) + } else { + return MongoManager.destroyDoc(doc_id, callback) + } + }) + }, - destroyAllDocs(project_id, callback) { - if (callback == null) { callback = function(err) {}; } - return MongoManager.getProjectsDocs(project_id, {include_deleted: true}, {_id: 1}, function(err, docs) { - if (err != null) { - logger.err({err, project_id}, "error getting project's docs"); - return callback(err); - } else if ((docs == null)) { - return callback(); - } - const jobs = _.map(docs, doc => cb => DocArchive.destroyDoc(project_id, doc._id, cb)); - return async.parallelLimit(jobs, 5, callback); - }); - }, + _deleteDocFromS3(project_id, doc_id, callback) { + let options + try { + options = DocArchive.buildS3Options(project_id + '/' + doc_id) + } catch (e) { + return callback(e) + } + options.json = true + return request.del(options, function(err, res, body) { + if (err != null || res.statusCode !== 204) { + logger.err( + { err, res, project_id, doc_id }, + 'something went wrong deleting doc from aws' + ) + return callback(new Error('Error in S3 request')) + } + return callback() + }) + }, - destroyDoc(project_id, doc_id, callback){ - logger.log({project_id, doc_id}, "removing doc from mongo and s3"); - return MongoManager.findDoc(project_id, doc_id, {inS3: 1}, function(error, doc) { - if (error != null) { return callback(error); } - if (doc == null) { return callback(new Errors.NotFoundError("Doc not found in Mongo")); } - if (doc.inS3 === true) { - return DocArchive._deleteDocFromS3(project_id, doc_id, function(err) { - if (err != null) { return err; } - return MongoManager.destroyDoc(doc_id, callback); - }); - } else { - return MongoManager.destroyDoc(doc_id, callback); - } - }); - }, + _s3DocToMongoDoc(doc, callback) { + if (callback == null) { + callback = function(error, mongo_doc) {} + } + const mongo_doc = {} + if (doc.schema_v === 1 && doc.lines != null) { + mongo_doc.lines = doc.lines + if (doc.ranges != null) { + mongo_doc.ranges = RangeManager.jsonRangesToMongo(doc.ranges) + } + } else if (doc instanceof Array) { + mongo_doc.lines = doc + } else { + return callback(new Error("I don't understand the doc format in s3")) + } + return callback(null, mongo_doc) + }, - _deleteDocFromS3(project_id, doc_id, callback) { - let options; - try { - options = DocArchive.buildS3Options(project_id+"/"+doc_id); - } catch (e) { - return callback(e); - } - options.json = true; - return request.del(options, function(err, res, body){ - if ((err != null) || (res.statusCode !== 204)) { - logger.err({err, res, project_id, doc_id}, "something went wrong deleting doc from aws"); - return callback(new Error("Error in S3 request")); - } - return callback(); - }); - }, + _mongoDocToS3Doc(doc, callback) { + if (callback == null) { + callback = function(error, s3_doc) {} + } + if (doc.lines == null) { + return callback(new Error('doc has no lines')) + } + const json = JSON.stringify({ + lines: doc.lines, + ranges: doc.ranges, + schema_v: 1 + }) + if (json.indexOf('\u0000') !== -1) { + const error = new Error('null bytes detected') + logger.err({ err: error, doc, json }, error.message) + return callback(error) + } + return callback(null, json) + }, - _s3DocToMongoDoc(doc, callback) { - if (callback == null) { callback = function(error, mongo_doc) {}; } - const mongo_doc = {}; - if ((doc.schema_v === 1) && (doc.lines != null)) { - mongo_doc.lines = doc.lines; - if (doc.ranges != null) { - mongo_doc.ranges = RangeManager.jsonRangesToMongo(doc.ranges); - } - } else if (doc instanceof Array) { - mongo_doc.lines = doc; - } else { - return callback(new Error("I don't understand the doc format in s3")); - } - return callback(null, mongo_doc); - }, - - _mongoDocToS3Doc(doc, callback) { - if (callback == null) { callback = function(error, s3_doc) {}; } - if ((doc.lines == null)) { - return callback(new Error("doc has no lines")); - } - const json = JSON.stringify({ - lines: doc.lines, - ranges: doc.ranges, - schema_v: 1 - }); - if (json.indexOf("\u0000") !== -1) { - const error = new Error("null bytes detected"); - logger.err({err: error, doc, json}, error.message); - return callback(error); - } - return callback(null, json); - }, - - buildS3Options(key){ - if ((settings.docstore.s3 == null)) { - throw new Error("S3 settings are not configured"); - } - return { - aws: { - key: settings.docstore.s3.key, - secret: settings.docstore.s3.secret, - bucket: settings.docstore.s3.bucket - }, - timeout: thirtySeconds, - uri:`https://${settings.docstore.s3.bucket}.s3.amazonaws.com/${key}` - }; - } -}); + buildS3Options(key) { + if (settings.docstore.s3 == null) { + throw new Error('S3 settings are not configured') + } + return { + aws: { + key: settings.docstore.s3.key, + secret: settings.docstore.s3.secret, + bucket: settings.docstore.s3.bucket + }, + timeout: thirtySeconds, + uri: `https://${settings.docstore.s3.bucket}.s3.amazonaws.com/${key}` + } + } +} diff --git a/services/docstore/app/js/DocManager.js b/services/docstore/app/js/DocManager.js index bddb1ee937..15a782861b 100644 --- a/services/docstore/app/js/DocManager.js +++ b/services/docstore/app/js/DocManager.js @@ -13,181 +13,277 @@ * DS207: Consider shorter variations of null checks * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -let DocManager; -const MongoManager = require("./MongoManager"); -const Errors = require("./Errors"); -const logger = require("logger-sharelatex"); -const _ = require("underscore"); -const DocArchive = require("./DocArchiveManager"); -const RangeManager = require("./RangeManager"); +let DocManager +const MongoManager = require('./MongoManager') +const Errors = require('./Errors') +const logger = require('logger-sharelatex') +const _ = require('underscore') +const DocArchive = require('./DocArchiveManager') +const RangeManager = require('./RangeManager') -module.exports = (DocManager = { - +module.exports = DocManager = { + // TODO: For historical reasons, the doc version is currently stored in the docOps + // collection (which is all that this collection contains). In future, we should + // migrate this version property to be part of the docs collection, to guarantee + // consitency between lines and version when writing/reading, and for a simpler schema. + _getDoc(project_id, doc_id, filter, callback) { + if (filter == null) { + filter = {} + } + if (callback == null) { + callback = function(error, doc) {} + } + if (filter.inS3 !== true) { + return callback('must include inS3 when getting doc') + } - // TODO: For historical reasons, the doc version is currently stored in the docOps - // collection (which is all that this collection contains). In future, we should - // migrate this version property to be part of the docs collection, to guarantee - // consitency between lines and version when writing/reading, and for a simpler schema. - _getDoc(project_id, doc_id, filter, callback) { - if (filter == null) { filter = {}; } - if (callback == null) { callback = function(error, doc) {}; } - if (filter.inS3 !== true) { - return callback("must include inS3 when getting doc"); - } + return MongoManager.findDoc(project_id, doc_id, filter, function(err, doc) { + if (err != null) { + return callback(err) + } else if (doc == null) { + return callback( + new Errors.NotFoundError( + `No such doc: ${doc_id} in project ${project_id}` + ) + ) + } else if (doc != null ? doc.inS3 : undefined) { + return DocArchive.unarchiveDoc(project_id, doc_id, function(err) { + if (err != null) { + logger.err({ err, project_id, doc_id }, 'error unarchiving doc') + return callback(err) + } + return DocManager._getDoc(project_id, doc_id, filter, callback) + }) + } else { + if (filter.version) { + return MongoManager.getDocVersion(doc_id, function(error, version) { + if (error != null) { + return callback(error) + } + doc.version = version + return callback(err, doc) + }) + } else { + return callback(err, doc) + } + } + }) + }, - return MongoManager.findDoc(project_id, doc_id, filter, function(err, doc){ - if (err != null) { - return callback(err); - } else if ((doc == null)) { - return callback(new Errors.NotFoundError(`No such doc: ${doc_id} in project ${project_id}`)); - } else if ((doc != null ? doc.inS3 : undefined)) { - return DocArchive.unarchiveDoc(project_id, doc_id, function(err){ - if (err != null) { - logger.err({err, project_id, doc_id}, "error unarchiving doc"); - return callback(err); - } - return DocManager._getDoc(project_id, doc_id, filter, callback); - }); - } else { - if (filter.version) { - return MongoManager.getDocVersion(doc_id, function(error, version) { - if (error != null) { return callback(error); } - doc.version = version; - return callback(err, doc); - }); - } else { - return callback(err, doc); - } - } - }); - }, + checkDocExists(project_id, doc_id, callback) { + if (callback == null) { + callback = function(err, exists) {} + } + return DocManager._getDoc( + project_id, + doc_id, + { _id: 1, inS3: true }, + function(err, doc) { + if (err != null) { + return callback(err) + } + return callback(err, doc != null) + } + ) + }, - checkDocExists(project_id, doc_id, callback){ - if (callback == null) { callback = function(err, exists){}; } - return DocManager._getDoc(project_id, doc_id, {_id:1, inS3:true}, function(err, doc){ - if (err != null) { - return callback(err); - } - return callback(err, (doc != null)); - }); - }, + getFullDoc(project_id, doc_id, callback) { + if (callback == null) { + callback = function(err, doc) {} + } + return DocManager._getDoc( + project_id, + doc_id, + { + lines: true, + rev: true, + deleted: true, + version: true, + ranges: true, + inS3: true + }, + function(err, doc) { + if (err != null) { + return callback(err) + } + return callback(err, doc) + } + ) + }, - getFullDoc(project_id, doc_id, callback){ - if (callback == null) { callback = function(err, doc){}; } - return DocManager._getDoc(project_id, doc_id, {lines: true, rev: true, deleted: true, version: true, ranges: true, inS3:true}, function(err, doc){ - if (err != null) { - return callback(err); - } - return callback(err, doc); - }); - }, + getDocLines(project_id, doc_id, callback) { + if (callback == null) { + callback = function(err, doc) {} + } + return DocManager._getDoc( + project_id, + doc_id, + { lines: true, inS3: true }, + function(err, doc) { + if (err != null) { + return callback(err) + } + return callback(err, doc) + } + ) + }, + getAllNonDeletedDocs(project_id, filter, callback) { + if (callback == null) { + callback = function(error, docs) {} + } + return DocArchive.unArchiveAllDocs(project_id, function(error) { + if (error != null) { + return callback(error) + } + return MongoManager.getProjectsDocs( + project_id, + { include_deleted: false }, + filter, + function(error, docs) { + if (typeof err !== 'undefined' && err !== null) { + return callback(error) + } else if (docs == null) { + return callback( + new Errors.NotFoundError(`No docs for project ${project_id}`) + ) + } else { + return callback(null, docs) + } + } + ) + }) + }, - getDocLines(project_id, doc_id, callback){ - if (callback == null) { callback = function(err, doc){}; } - return DocManager._getDoc(project_id, doc_id, {lines:true, inS3:true}, function(err, doc){ - if (err != null) { - return callback(err); - } - return callback(err, doc); - }); - }, + updateDoc(project_id, doc_id, lines, version, ranges, callback) { + if (callback == null) { + callback = function(error, modified, rev) {} + } + if (lines == null || version == null || ranges == null) { + return callback(new Error('no lines, version or ranges provided')) + } - getAllNonDeletedDocs(project_id, filter, callback) { - if (callback == null) { callback = function(error, docs) {}; } - return DocArchive.unArchiveAllDocs(project_id, function(error) { - if (error != null) { - return callback(error); - } - return MongoManager.getProjectsDocs(project_id, {include_deleted: false}, filter, function(error, docs) { - if (typeof err !== 'undefined' && err !== null) { - return callback(error); - } else if ((docs == null)) { - return callback(new Errors.NotFoundError(`No docs for project ${project_id}`)); - } else { - return callback(null, docs); - } - }); - }); - }, + return DocManager._getDoc( + project_id, + doc_id, + { + version: true, + rev: true, + lines: true, + version: true, + ranges: true, + inS3: true + }, + function(err, doc) { + let updateLines, updateRanges, updateVersion + if (err != null && !(err instanceof Errors.NotFoundError)) { + logger.err( + { project_id, doc_id, err }, + 'error getting document for update' + ) + return callback(err) + } - updateDoc(project_id, doc_id, lines, version, ranges, callback) { - if (callback == null) { callback = function(error, modified, rev) {}; } - if ((lines == null) || (version == null) || (ranges == null)) { - return callback(new Error("no lines, version or ranges provided")); - } - - return DocManager._getDoc(project_id, doc_id, {version: true, rev: true, lines: true, version: true, ranges: true, inS3:true}, function(err, doc){ - let updateLines, updateRanges, updateVersion; - if ((err != null) && !(err instanceof Errors.NotFoundError)) { - logger.err({project_id, doc_id, err}, "error getting document for update"); - return callback(err); - } - - ranges = RangeManager.jsonRangesToMongo(ranges); + ranges = RangeManager.jsonRangesToMongo(ranges) - if ((doc == null)) { - // If the document doesn't exist, we'll make sure to create/update all parts of it. - updateLines = true; - updateVersion = true; - updateRanges = true; - } else { - updateLines = !_.isEqual(doc.lines, lines); - updateVersion = (doc.version !== version); - updateRanges = RangeManager.shouldUpdateRanges(doc.ranges, ranges); - } - - let modified = false; - let rev = (doc != null ? doc.rev : undefined) || 0; + if (doc == null) { + // If the document doesn't exist, we'll make sure to create/update all parts of it. + updateLines = true + updateVersion = true + updateRanges = true + } else { + updateLines = !_.isEqual(doc.lines, lines) + updateVersion = doc.version !== version + updateRanges = RangeManager.shouldUpdateRanges(doc.ranges, ranges) + } - const updateLinesAndRangesIfNeeded = function(cb) { - if (updateLines || updateRanges) { - const update = {}; - if (updateLines) { - update.lines = lines; - } - if (updateRanges) { - update.ranges = ranges; - } - logger.log({ project_id, doc_id }, "updating doc lines and ranges"); - - modified = true; - rev += 1; // rev will be incremented in mongo by MongoManager.upsertIntoDocCollection - return MongoManager.upsertIntoDocCollection(project_id, doc_id, update, cb); - } else { - logger.log({ project_id, doc_id, }, "doc lines have not changed - not updating"); - return cb(); - } - }; - - const updateVersionIfNeeded = function(cb) { - if (updateVersion) { - logger.log({ project_id, doc_id, oldVersion: (doc != null ? doc.version : undefined), newVersion: version }, "updating doc version"); - modified = true; - return MongoManager.setDocVersion(doc_id, version, cb); - } else { - logger.log({ project_id, doc_id, version }, "doc version has not changed - not updating"); - return cb(); - } - }; - - return updateLinesAndRangesIfNeeded(function(error) { - if (error != null) { return callback(error); } - return updateVersionIfNeeded(function(error) { - if (error != null) { return callback(error); } - return callback(null, modified, rev); - }); - }); - }); - }, + let modified = false + let rev = (doc != null ? doc.rev : undefined) || 0 - deleteDoc(project_id, doc_id, callback) { - if (callback == null) { callback = function(error) {}; } - return DocManager.checkDocExists(project_id, doc_id, function(error, exists) { - if (error != null) { return callback(error); } - if (!exists) { return callback(new Errors.NotFoundError(`No such project/doc to delete: ${project_id}/${doc_id}`)); } - return MongoManager.markDocAsDeleted(project_id, doc_id, callback); - }); - } -}); + const updateLinesAndRangesIfNeeded = function(cb) { + if (updateLines || updateRanges) { + const update = {} + if (updateLines) { + update.lines = lines + } + if (updateRanges) { + update.ranges = ranges + } + logger.log({ project_id, doc_id }, 'updating doc lines and ranges') + modified = true + rev += 1 // rev will be incremented in mongo by MongoManager.upsertIntoDocCollection + return MongoManager.upsertIntoDocCollection( + project_id, + doc_id, + update, + cb + ) + } else { + logger.log( + { project_id, doc_id }, + 'doc lines have not changed - not updating' + ) + return cb() + } + } + + const updateVersionIfNeeded = function(cb) { + if (updateVersion) { + logger.log( + { + project_id, + doc_id, + oldVersion: doc != null ? doc.version : undefined, + newVersion: version + }, + 'updating doc version' + ) + modified = true + return MongoManager.setDocVersion(doc_id, version, cb) + } else { + logger.log( + { project_id, doc_id, version }, + 'doc version has not changed - not updating' + ) + return cb() + } + } + + return updateLinesAndRangesIfNeeded(function(error) { + if (error != null) { + return callback(error) + } + return updateVersionIfNeeded(function(error) { + if (error != null) { + return callback(error) + } + return callback(null, modified, rev) + }) + }) + } + ) + }, + + deleteDoc(project_id, doc_id, callback) { + if (callback == null) { + callback = function(error) {} + } + return DocManager.checkDocExists(project_id, doc_id, function( + error, + exists + ) { + if (error != null) { + return callback(error) + } + if (!exists) { + return callback( + new Errors.NotFoundError( + `No such project/doc to delete: ${project_id}/${doc_id}` + ) + ) + } + return MongoManager.markDocAsDeleted(project_id, doc_id, callback) + }) + } +} diff --git a/services/docstore/app/js/Errors.js b/services/docstore/app/js/Errors.js index a000b8f1f4..f3bc8e37eb 100644 --- a/services/docstore/app/js/Errors.js +++ b/services/docstore/app/js/Errors.js @@ -4,15 +4,13 @@ */ // TODO: This file was created by bulk-decaffeinate. // Fix any style issues and re-enable lint. -let Errors; +let Errors var NotFoundError = function(message) { - const error = new Error(message); - error.name = "NotFoundError"; - error.__proto__ = NotFoundError.prototype; - return error; -}; -NotFoundError.prototype.__proto__ = Error.prototype; - -module.exports = (Errors = - {NotFoundError}); + const error = new Error(message) + error.name = 'NotFoundError' + error.__proto__ = NotFoundError.prototype + return error +} +NotFoundError.prototype.__proto__ = Error.prototype +module.exports = Errors = { NotFoundError } diff --git a/services/docstore/app/js/HealthChecker.js b/services/docstore/app/js/HealthChecker.js index 143e797f4e..87b16a9951 100644 --- a/services/docstore/app/js/HealthChecker.js +++ b/services/docstore/app/js/HealthChecker.js @@ -10,56 +10,59 @@ * DS207: Consider shorter variations of null checks * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const {db, ObjectId} = require("./mongojs"); -const request = require("request"); -const async = require("async"); -const _ = require("underscore"); -const crypto = require("crypto"); -const settings = require("settings-sharelatex"); -const { - port -} = settings.internal.docstore; -const logger = require("logger-sharelatex"); +const { db, ObjectId } = require('./mongojs') +const request = require('request') +const async = require('async') +const _ = require('underscore') +const crypto = require('crypto') +const settings = require('settings-sharelatex') +const { port } = settings.internal.docstore +const logger = require('logger-sharelatex') - -module.exports = { - check(callback){ - const doc_id = ObjectId(); - const project_id = ObjectId(settings.docstore.healthCheck.project_id); - const url = `http://localhost:${port}/project/${project_id}/doc/${doc_id}`; - const lines = ["smoke test - delete me", `${crypto.randomBytes(32).toString("hex")}`]; - const getOpts = () => ({ - url, - timeout:3000 - }); - logger.log({lines, url, doc_id, project_id}, "running health check"); - const jobs = [ - function(cb){ - const opts = getOpts(); - opts.json = {lines, version: 42, ranges: {}}; - return request.post(opts, cb); - }, - function(cb){ - const opts = getOpts(); - opts.json = true; - return request.get(opts, function(err, res, body){ - if (err != null) { - logger.err({err}, "docstore returned a error in health check get"); - return cb(err); - } else if ((res == null)) { - return cb("no response from docstore with get check"); - } else if ((res != null ? res.statusCode : undefined) !== 200) { - return cb(`status code not 200, its ${res.statusCode}`); - } else if (_.isEqual(body != null ? body.lines : undefined, lines) && ((body != null ? body._id : undefined) === doc_id.toString())) { - return cb(); - } else { - return cb(`health check lines not equal ${body.lines} != ${lines}`); - } - }); - }, - cb => db.docs.remove({_id: doc_id, project_id}, cb), - cb => db.docOps.remove({doc_id}, cb) - ]; - return async.series(jobs, callback); - } -}; +module.exports = { + check(callback) { + const doc_id = ObjectId() + const project_id = ObjectId(settings.docstore.healthCheck.project_id) + const url = `http://localhost:${port}/project/${project_id}/doc/${doc_id}` + const lines = [ + 'smoke test - delete me', + `${crypto.randomBytes(32).toString('hex')}` + ] + const getOpts = () => ({ + url, + timeout: 3000 + }) + logger.log({ lines, url, doc_id, project_id }, 'running health check') + const jobs = [ + function(cb) { + const opts = getOpts() + opts.json = { lines, version: 42, ranges: {} } + return request.post(opts, cb) + }, + function(cb) { + const opts = getOpts() + opts.json = true + return request.get(opts, function(err, res, body) { + if (err != null) { + logger.err({ err }, 'docstore returned a error in health check get') + return cb(err) + } else if (res == null) { + return cb('no response from docstore with get check') + } else if ((res != null ? res.statusCode : undefined) !== 200) { + return cb(`status code not 200, its ${res.statusCode}`) + } else if ( + _.isEqual(body != null ? body.lines : undefined, lines) && + (body != null ? body._id : undefined) === doc_id.toString() + ) { + return cb() + } else { + return cb(`health check lines not equal ${body.lines} != ${lines}`) + } + }) + }, + cb => db.docs.remove({ _id: doc_id, project_id }, cb), + cb => db.docOps.remove({ doc_id }, cb) + ] + return async.series(jobs, callback) + } +} diff --git a/services/docstore/app/js/HttpController.js b/services/docstore/app/js/HttpController.js index 7f6eb9e728..7e17c15b65 100644 --- a/services/docstore/app/js/HttpController.js +++ b/services/docstore/app/js/HttpController.js @@ -12,220 +12,252 @@ * DS207: Consider shorter variations of null checks * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -let HttpController; -const DocManager = require("./DocManager"); -const logger = require("logger-sharelatex"); -const DocArchive = require("./DocArchiveManager"); -const HealthChecker = require("./HealthChecker"); -const Settings = require("settings-sharelatex"); +let HttpController +const DocManager = require('./DocManager') +const logger = require('logger-sharelatex') +const DocArchive = require('./DocArchiveManager') +const HealthChecker = require('./HealthChecker') +const Settings = require('settings-sharelatex') +module.exports = HttpController = { + getDoc(req, res, next) { + if (next == null) { + next = function(error) {} + } + const { project_id } = req.params + const { doc_id } = req.params + const include_deleted = + (req.query != null ? req.query.include_deleted : undefined) === 'true' + logger.log({ project_id, doc_id }, 'getting doc') + return DocManager.getFullDoc(project_id, doc_id, function(error, doc) { + if (error != null) { + return next(error) + } + logger.log({ doc_id, project_id }, 'got doc') + if (doc == null) { + return res.send(404) + } else if (doc.deleted && !include_deleted) { + return res.send(404) + } else { + return res.json(HttpController._buildDocView(doc)) + } + }) + }, -module.exports = (HttpController = { - getDoc(req, res, next) { - if (next == null) { next = function(error) {}; } - const { - project_id - } = req.params; - const { - doc_id - } = req.params; - const include_deleted = (req.query != null ? req.query.include_deleted : undefined) === "true"; - logger.log({project_id, doc_id}, "getting doc"); - return DocManager.getFullDoc(project_id, doc_id, function(error, doc) { - if (error != null) { return next(error); } - logger.log({doc_id, project_id}, "got doc"); - if ((doc == null)) { - return res.send(404); - } else if (doc.deleted && !include_deleted) { - return res.send(404); - } else { - return res.json(HttpController._buildDocView(doc)); - } - }); - }, + getRawDoc(req, res, next) { + if (next == null) { + next = function(error) {} + } + const { project_id } = req.params + const { doc_id } = req.params + logger.log({ project_id, doc_id }, 'getting raw doc') + return DocManager.getDocLines(project_id, doc_id, function(error, doc) { + if (error != null) { + return next(error) + } + if (doc == null) { + return res.send(404) + } else { + res.setHeader('content-type', 'text/plain') + return res.send(HttpController._buildRawDocView(doc)) + } + }) + }, - getRawDoc(req, res, next){ - if (next == null) { next = function(error){}; } - const { - project_id - } = req.params; - const { - doc_id - } = req.params; - logger.log({project_id, doc_id}, "getting raw doc"); - return DocManager.getDocLines(project_id, doc_id, function(error, doc) { - if (error != null) { return next(error); } - if ((doc == null)) { - return res.send(404); - } else { - res.setHeader('content-type', 'text/plain'); - return res.send(HttpController._buildRawDocView(doc)); - } - }); - }, + getAllDocs(req, res, next) { + if (next == null) { + next = function(error) {} + } + const { project_id } = req.params + logger.log({ project_id }, 'getting all docs') + return DocManager.getAllNonDeletedDocs( + project_id, + { lines: true, rev: true }, + function(error, docs) { + if (docs == null) { + docs = [] + } + if (error != null) { + return next(error) + } + return res.json(HttpController._buildDocsArrayView(project_id, docs)) + } + ) + }, - getAllDocs(req, res, next) { - if (next == null) { next = function(error) {}; } - const { - project_id - } = req.params; - logger.log({project_id}, "getting all docs"); - return DocManager.getAllNonDeletedDocs(project_id, {lines: true, rev: true}, function(error, docs) { - if (docs == null) { docs = []; } - if (error != null) { return next(error); } - return res.json(HttpController._buildDocsArrayView(project_id, docs)); - }); - }, - - getAllRanges(req, res, next) { - if (next == null) { next = function(error) {}; } - const { - project_id - } = req.params; - logger.log({project_id}, "getting all ranges"); - return DocManager.getAllNonDeletedDocs(project_id, {ranges: true}, function(error, docs) { - if (docs == null) { docs = []; } - if (error != null) { return next(error); } - return res.json(HttpController._buildDocsArrayView(project_id, docs)); - }); - }, + getAllRanges(req, res, next) { + if (next == null) { + next = function(error) {} + } + const { project_id } = req.params + logger.log({ project_id }, 'getting all ranges') + return DocManager.getAllNonDeletedDocs( + project_id, + { ranges: true }, + function(error, docs) { + if (docs == null) { + docs = [] + } + if (error != null) { + return next(error) + } + return res.json(HttpController._buildDocsArrayView(project_id, docs)) + } + ) + }, - updateDoc(req, res, next) { - if (next == null) { next = function(error) {}; } - const { - project_id - } = req.params; - const { - doc_id - } = req.params; - const lines = req.body != null ? req.body.lines : undefined; - const version = req.body != null ? req.body.version : undefined; - const ranges = req.body != null ? req.body.ranges : undefined; + updateDoc(req, res, next) { + if (next == null) { + next = function(error) {} + } + const { project_id } = req.params + const { doc_id } = req.params + const lines = req.body != null ? req.body.lines : undefined + const version = req.body != null ? req.body.version : undefined + const ranges = req.body != null ? req.body.ranges : undefined - if ((lines == null) || !(lines instanceof Array)) { - logger.error({project_id, doc_id}, "no doc lines provided"); - res.send(400); // Bad Request - return; - } - - if ((version == null) || (typeof version === !"number")) { - logger.error({project_id, doc_id}, "no doc version provided"); - res.send(400); // Bad Request - return; - } - - if ((ranges == null)) { - logger.error({project_id, doc_id}, "no doc ranges provided"); - res.send(400); // Bad Request - return; - } + if (lines == null || !(lines instanceof Array)) { + logger.error({ project_id, doc_id }, 'no doc lines provided') + res.send(400) // Bad Request + return + } - const bodyLength = lines.reduce( - (len, line) => line.length + len, - 0 - ); - if (bodyLength > Settings.max_doc_length) { - logger.error({project_id, doc_id, bodyLength}, "document body too large"); - res.status(413).send("document body too large"); - return; - } + if (version == null || typeof version === !'number') { + logger.error({ project_id, doc_id }, 'no doc version provided') + res.send(400) // Bad Request + return + } - logger.log({project_id, doc_id}, "got http request to update doc"); - return DocManager.updateDoc(project_id, doc_id, lines, version, ranges, function(error, modified, rev) { - if (error != null) { return next(error); } - return res.json({ - modified, - rev - }); - }); - }, + if (ranges == null) { + logger.error({ project_id, doc_id }, 'no doc ranges provided') + res.send(400) // Bad Request + return + } - deleteDoc(req, res, next) { - if (next == null) { next = function(error) {}; } - const { - project_id - } = req.params; - const { - doc_id - } = req.params; - logger.log({project_id, doc_id}, "deleting doc"); - return DocManager.deleteDoc(project_id, doc_id, function(error) { - if (error != null) { return next(error); } - return res.send(204); - }); - }, + const bodyLength = lines.reduce((len, line) => line.length + len, 0) + if (bodyLength > Settings.max_doc_length) { + logger.error( + { project_id, doc_id, bodyLength }, + 'document body too large' + ) + res.status(413).send('document body too large') + return + } - _buildDocView(doc) { - const doc_view = { _id: (doc._id != null ? doc._id.toString() : undefined) }; - for (const attribute of ["lines", "rev", "version", "ranges", "deleted"]) { - if (doc[attribute] != null) { - doc_view[attribute] = doc[attribute]; - } - } - return doc_view; - }, + logger.log({ project_id, doc_id }, 'got http request to update doc') + return DocManager.updateDoc( + project_id, + doc_id, + lines, + version, + ranges, + function(error, modified, rev) { + if (error != null) { + return next(error) + } + return res.json({ + modified, + rev + }) + } + ) + }, - _buildRawDocView(doc){ - return ((doc != null ? doc.lines : undefined) || []).join("\n"); - }, - - _buildDocsArrayView(project_id, docs) { - const docViews = []; - for (const doc of Array.from(docs)) { - if (doc != null) { // There can end up being null docs for some reason :( (probably a race condition) - docViews.push(HttpController._buildDocView(doc)); - } else { - logger.error({err: new Error("null doc"), project_id}, "encountered null doc"); - } - } - return docViews; - }, + deleteDoc(req, res, next) { + if (next == null) { + next = function(error) {} + } + const { project_id } = req.params + const { doc_id } = req.params + logger.log({ project_id, doc_id }, 'deleting doc') + return DocManager.deleteDoc(project_id, doc_id, function(error) { + if (error != null) { + return next(error) + } + return res.send(204) + }) + }, - archiveAllDocs(req, res, next) { - if (next == null) { next = function(error) {}; } - const { - project_id - } = req.params; - logger.log({project_id}, "archiving all docs"); - return DocArchive.archiveAllDocs(project_id, function(error) { - if (error != null) { return next(error); } - return res.send(204); - }); - }, + _buildDocView(doc) { + const doc_view = { _id: doc._id != null ? doc._id.toString() : undefined } + for (const attribute of ['lines', 'rev', 'version', 'ranges', 'deleted']) { + if (doc[attribute] != null) { + doc_view[attribute] = doc[attribute] + } + } + return doc_view + }, - unArchiveAllDocs(req, res, next) { - if (next == null) { next = function(error) {}; } - const { - project_id - } = req.params; - logger.log({project_id}, "unarchiving all docs"); - return DocArchive.unArchiveAllDocs(project_id, function(error) { - if (error != null) { return next(error); } - return res.send(200); - }); - }, + _buildRawDocView(doc) { + return ((doc != null ? doc.lines : undefined) || []).join('\n') + }, - destroyAllDocs(req, res, next) { - if (next == null) { next = function(error) {}; } - const { - project_id - } = req.params; - logger.log({project_id}, "destroying all docs"); - return DocArchive.destroyAllDocs(project_id, function(error) { - if (error != null) { return next(error); } - return res.send(204); - }); - }, + _buildDocsArrayView(project_id, docs) { + const docViews = [] + for (const doc of Array.from(docs)) { + if (doc != null) { + // There can end up being null docs for some reason :( (probably a race condition) + docViews.push(HttpController._buildDocView(doc)) + } else { + logger.error( + { err: new Error('null doc'), project_id }, + 'encountered null doc' + ) + } + } + return docViews + }, - healthCheck(req, res){ - return HealthChecker.check(function(err){ - if (err != null) { - logger.err({err}, "error performing health check"); - return res.send(500); - } else { - return res.send(200); - } - }); - } -}); + archiveAllDocs(req, res, next) { + if (next == null) { + next = function(error) {} + } + const { project_id } = req.params + logger.log({ project_id }, 'archiving all docs') + return DocArchive.archiveAllDocs(project_id, function(error) { + if (error != null) { + return next(error) + } + return res.send(204) + }) + }, + unArchiveAllDocs(req, res, next) { + if (next == null) { + next = function(error) {} + } + const { project_id } = req.params + logger.log({ project_id }, 'unarchiving all docs') + return DocArchive.unArchiveAllDocs(project_id, function(error) { + if (error != null) { + return next(error) + } + return res.send(200) + }) + }, + + destroyAllDocs(req, res, next) { + if (next == null) { + next = function(error) {} + } + const { project_id } = req.params + logger.log({ project_id }, 'destroying all docs') + return DocArchive.destroyAllDocs(project_id, function(error) { + if (error != null) { + return next(error) + } + return res.send(204) + }) + }, + + healthCheck(req, res) { + return HealthChecker.check(function(err) { + if (err != null) { + logger.err({ err }, 'error performing health check') + return res.send(500) + } else { + return res.send(200) + } + }) + } +} diff --git a/services/docstore/app/js/MongoManager.js b/services/docstore/app/js/MongoManager.js index 27918267f9..413f60be82 100644 --- a/services/docstore/app/js/MongoManager.js +++ b/services/docstore/app/js/MongoManager.js @@ -10,122 +10,167 @@ * DS207: Consider shorter variations of null checks * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -let MongoManager; -const {db, ObjectId} = require("./mongojs"); -const logger = require('logger-sharelatex'); -const metrics = require('metrics-sharelatex'); +let MongoManager +const { db, ObjectId } = require('./mongojs') +const logger = require('logger-sharelatex') +const metrics = require('metrics-sharelatex') -module.exports = (MongoManager = { +module.exports = MongoManager = { + findDoc(project_id, doc_id, filter, callback) { + if (callback == null) { + callback = function(error, doc) {} + } + return db.docs.find( + { + _id: ObjectId(doc_id.toString()), + project_id: ObjectId(project_id.toString()) + }, + filter, + function(error, docs) { + if (docs == null) { + docs = [] + } + return callback(error, docs[0]) + } + ) + }, - findDoc(project_id, doc_id, filter, callback) { - if (callback == null) { callback = function(error, doc) {}; } - return db.docs.find({_id: ObjectId(doc_id.toString()), project_id: ObjectId(project_id.toString())}, filter, function(error, docs) { - if (docs == null) { docs = []; } - return callback(error, docs[0]); - }); - }, + getProjectsDocs(project_id, options, filter, callback) { + if (options == null) { + options = { include_deleted: true } + } + const query = { project_id: ObjectId(project_id.toString()) } + if (!options.include_deleted) { + query.deleted = { $ne: true } + } + return db.docs.find(query, filter, callback) + }, - getProjectsDocs(project_id, options, filter, callback){ - if (options == null) { options = {include_deleted: true}; } - const query = {project_id: ObjectId(project_id.toString())}; - if (!options.include_deleted) { - query.deleted = { $ne: true }; - } - return db.docs.find(query, filter, callback); - }, + getArchivedProjectDocs(project_id, callback) { + const query = { + project_id: ObjectId(project_id.toString()), + inS3: true + } + return db.docs.find(query, {}, callback) + }, - getArchivedProjectDocs(project_id, callback){ - const query = { - project_id: ObjectId(project_id.toString()), - inS3: true - }; - return db.docs.find(query, {}, callback); - }, + upsertIntoDocCollection(project_id, doc_id, updates, callback) { + const update = { + $set: updates, + $inc: { + rev: 1 + }, + $unset: { + inS3: true + } + } + update.$set.project_id = ObjectId(project_id) + return db.docs.update( + { _id: ObjectId(doc_id) }, + update, + { upsert: true }, + callback + ) + }, - upsertIntoDocCollection(project_id, doc_id, updates, callback){ - const update = { - $set: updates, - $inc: { - rev: 1 - }, - $unset: { - inS3: true - } - }; - update.$set.project_id = ObjectId(project_id); - return db.docs.update({_id: ObjectId(doc_id)}, update, {upsert: true}, callback); - }, + markDocAsDeleted(project_id, doc_id, callback) { + return db.docs.update( + { + _id: ObjectId(doc_id), + project_id: ObjectId(project_id) + }, + { + $set: { deleted: true } + }, + callback + ) + }, - markDocAsDeleted(project_id, doc_id, callback){ - return db.docs.update({ - _id: ObjectId(doc_id), - project_id: ObjectId(project_id) - }, { - $set: { deleted: true } - }, callback); - }, + markDocAsArchived(doc_id, rev, callback) { + const update = { + $set: {}, + $unset: {} + } + update.$set.inS3 = true + update.$unset.lines = true + update.$unset.ranges = true + const query = { + _id: doc_id, + rev + } + return db.docs.update(query, update, err => callback(err)) + }, - markDocAsArchived(doc_id, rev, callback){ - const update = { - $set: {}, - $unset: {} - }; - update.$set.inS3 = true; - update.$unset.lines = true; - update.$unset.ranges = true; - const query = { - _id: doc_id, - rev - }; - return db.docs.update(query, update, err => callback(err)); - }, - - getDocVersion(doc_id, callback) { - if (callback == null) { callback = function(error, version) {}; } - return db.docOps.find({ - doc_id: ObjectId(doc_id) - }, { - version: 1 - }, function(error, docs) { - if (error != null) { return callback(error); } - if ((docs.length < 1) || (docs[0].version == null)) { - return callback(null, 0); - } else { - return callback(null, docs[0].version); - } - }); - }, + getDocVersion(doc_id, callback) { + if (callback == null) { + callback = function(error, version) {} + } + return db.docOps.find( + { + doc_id: ObjectId(doc_id) + }, + { + version: 1 + }, + function(error, docs) { + if (error != null) { + return callback(error) + } + if (docs.length < 1 || docs[0].version == null) { + return callback(null, 0) + } else { + return callback(null, docs[0].version) + } + } + ) + }, - setDocVersion(doc_id, version, callback) { - if (callback == null) { callback = function(error) {}; } - return db.docOps.update({ - doc_id: ObjectId(doc_id) - }, { - $set: { version - } - }, { - upsert: true - }, callback); - }, + setDocVersion(doc_id, version, callback) { + if (callback == null) { + callback = function(error) {} + } + return db.docOps.update( + { + doc_id: ObjectId(doc_id) + }, + { + $set: { version } + }, + { + upsert: true + }, + callback + ) + }, - destroyDoc(doc_id, callback) { - return db.docs.remove({ - _id: ObjectId(doc_id) - }, function(err) { - if (err != null) { return callback(err); } - return db.docOps.remove({ - doc_id: ObjectId(doc_id) - }, callback); - }); - } -}); + destroyDoc(doc_id, callback) { + return db.docs.remove( + { + _id: ObjectId(doc_id) + }, + function(err) { + if (err != null) { + return callback(err) + } + return db.docOps.remove( + { + doc_id: ObjectId(doc_id) + }, + callback + ) + } + ) + } +} -[ - 'findDoc', - 'getProjectsDocs', - 'getArchivedProjectDocs', - 'upsertIntoDocCollection', - 'markDocAsArchived', - 'getDocVersion', - 'setDocVersion' -].map(method => metrics.timeAsyncMethod(MongoManager, method, 'mongo.MongoManager', logger)); +;[ + 'findDoc', + 'getProjectsDocs', + 'getArchivedProjectDocs', + 'upsertIntoDocCollection', + 'markDocAsArchived', + 'getDocVersion', + 'setDocVersion' +].map(method => + metrics.timeAsyncMethod(MongoManager, method, 'mongo.MongoManager', logger) +) diff --git a/services/docstore/app/js/RangeManager.js b/services/docstore/app/js/RangeManager.js index cee272a8e6..5a0061a9de 100644 --- a/services/docstore/app/js/RangeManager.js +++ b/services/docstore/app/js/RangeManager.js @@ -11,57 +11,59 @@ * DS207: Consider shorter variations of null checks * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -let RangeManager; -const _ = require("underscore"); -const {ObjectId} = require("./mongojs"); +let RangeManager +const _ = require('underscore') +const { ObjectId } = require('./mongojs') -module.exports = (RangeManager = { - shouldUpdateRanges(doc_ranges, incoming_ranges) { - if ((incoming_ranges == null)) { - throw new Error("expected incoming_ranges"); - } +module.exports = RangeManager = { + shouldUpdateRanges(doc_ranges, incoming_ranges) { + if (incoming_ranges == null) { + throw new Error('expected incoming_ranges') + } - // If the ranges are empty, we don't store them in the DB, so set - // doc_ranges to an empty object as default, since this is was the - // incoming_ranges will be for an empty range set. - if ((doc_ranges == null)) { - doc_ranges = {}; - } + // If the ranges are empty, we don't store them in the DB, so set + // doc_ranges to an empty object as default, since this is was the + // incoming_ranges will be for an empty range set. + if (doc_ranges == null) { + doc_ranges = {} + } - return !_.isEqual(doc_ranges, incoming_ranges); - }, - - jsonRangesToMongo(ranges) { - if ((ranges == null)) { return null; } - - const updateMetadata = function(metadata) { - if ((metadata != null ? metadata.ts : undefined) != null) { - metadata.ts = new Date(metadata.ts); - } - if ((metadata != null ? metadata.user_id : undefined) != null) { - return metadata.user_id = RangeManager._safeObjectId(metadata.user_id); - } - }; - - for (const change of Array.from(ranges.changes || [])) { - change.id = RangeManager._safeObjectId(change.id); - updateMetadata(change.metadata); - } - for (const comment of Array.from(ranges.comments || [])) { - comment.id = RangeManager._safeObjectId(comment.id); - if ((comment.op != null ? comment.op.t : undefined) != null) { - comment.op.t = RangeManager._safeObjectId(comment.op.t); - } - updateMetadata(comment.metadata); - } - return ranges; - }, - - _safeObjectId(data) { - try { - return ObjectId(data); - } catch (error) { - return data; - } - } -}); \ No newline at end of file + return !_.isEqual(doc_ranges, incoming_ranges) + }, + + jsonRangesToMongo(ranges) { + if (ranges == null) { + return null + } + + const updateMetadata = function(metadata) { + if ((metadata != null ? metadata.ts : undefined) != null) { + metadata.ts = new Date(metadata.ts) + } + if ((metadata != null ? metadata.user_id : undefined) != null) { + return (metadata.user_id = RangeManager._safeObjectId(metadata.user_id)) + } + } + + for (const change of Array.from(ranges.changes || [])) { + change.id = RangeManager._safeObjectId(change.id) + updateMetadata(change.metadata) + } + for (const comment of Array.from(ranges.comments || [])) { + comment.id = RangeManager._safeObjectId(comment.id) + if ((comment.op != null ? comment.op.t : undefined) != null) { + comment.op.t = RangeManager._safeObjectId(comment.op.t) + } + updateMetadata(comment.metadata) + } + return ranges + }, + + _safeObjectId(data) { + try { + return ObjectId(data) + } catch (error) { + return data + } + } +} diff --git a/services/docstore/app/js/mongojs.js b/services/docstore/app/js/mongojs.js index 8000129ae5..41f3bec470 100644 --- a/services/docstore/app/js/mongojs.js +++ b/services/docstore/app/js/mongojs.js @@ -1,10 +1,9 @@ // TODO: This file was created by bulk-decaffeinate. // Sanity-check the conversion and remove this comment. -const Settings = require("settings-sharelatex"); -const mongojs = require("mongojs"); -const db = mongojs(Settings.mongo.url, ["docs", "docOps"]); +const Settings = require('settings-sharelatex') +const mongojs = require('mongojs') +const db = mongojs(Settings.mongo.url, ['docs', 'docOps']) module.exports = { - db, - ObjectId: mongojs.ObjectId -}; - + db, + ObjectId: mongojs.ObjectId +} From 5098fa6d400a93bb7ddbf88dd2617285e81e33ec Mon Sep 17 00:00:00 2001 From: decaffeinate Date: Sun, 16 Feb 2020 14:02:47 +0000 Subject: [PATCH 09/27] decaffeinate: Rename DocArchiveManagerTests.coffee and 4 other files from .coffee to .js --- .../{DocArchiveManagerTests.coffee => DocArchiveManagerTests.js} | 0 .../unit/coffee/{DocManagerTests.coffee => DocManagerTests.js} | 0 .../coffee/{HttpControllerTests.coffee => HttpControllerTests.js} | 0 .../coffee/{MongoManagerTests.coffee => MongoManagerTests.js} | 0 .../coffee/{RangeManagerTests.coffee => RangeManagerTests.js} | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename services/docstore/test/unit/coffee/{DocArchiveManagerTests.coffee => DocArchiveManagerTests.js} (100%) rename services/docstore/test/unit/coffee/{DocManagerTests.coffee => DocManagerTests.js} (100%) rename services/docstore/test/unit/coffee/{HttpControllerTests.coffee => HttpControllerTests.js} (100%) rename services/docstore/test/unit/coffee/{MongoManagerTests.coffee => MongoManagerTests.js} (100%) rename services/docstore/test/unit/coffee/{RangeManagerTests.coffee => RangeManagerTests.js} (100%) diff --git a/services/docstore/test/unit/coffee/DocArchiveManagerTests.coffee b/services/docstore/test/unit/coffee/DocArchiveManagerTests.js similarity index 100% rename from services/docstore/test/unit/coffee/DocArchiveManagerTests.coffee rename to services/docstore/test/unit/coffee/DocArchiveManagerTests.js diff --git a/services/docstore/test/unit/coffee/DocManagerTests.coffee b/services/docstore/test/unit/coffee/DocManagerTests.js similarity index 100% rename from services/docstore/test/unit/coffee/DocManagerTests.coffee rename to services/docstore/test/unit/coffee/DocManagerTests.js diff --git a/services/docstore/test/unit/coffee/HttpControllerTests.coffee b/services/docstore/test/unit/coffee/HttpControllerTests.js similarity index 100% rename from services/docstore/test/unit/coffee/HttpControllerTests.coffee rename to services/docstore/test/unit/coffee/HttpControllerTests.js diff --git a/services/docstore/test/unit/coffee/MongoManagerTests.coffee b/services/docstore/test/unit/coffee/MongoManagerTests.js similarity index 100% rename from services/docstore/test/unit/coffee/MongoManagerTests.coffee rename to services/docstore/test/unit/coffee/MongoManagerTests.js diff --git a/services/docstore/test/unit/coffee/RangeManagerTests.coffee b/services/docstore/test/unit/coffee/RangeManagerTests.js similarity index 100% rename from services/docstore/test/unit/coffee/RangeManagerTests.coffee rename to services/docstore/test/unit/coffee/RangeManagerTests.js From 06bdba5c148d678391516aba8cd13824c340298d Mon Sep 17 00:00:00 2001 From: decaffeinate Date: Sun, 16 Feb 2020 14:02:48 +0000 Subject: [PATCH 10/27] decaffeinate: Convert DocArchiveManagerTests.coffee and 4 other files to JS --- .../unit/coffee/DocArchiveManagerTests.js | 628 ++++++++------ .../test/unit/coffee/DocManagerTests.js | 770 ++++++++++-------- .../test/unit/coffee/HttpControllerTests.js | 643 ++++++++------- .../test/unit/coffee/MongoManagerTests.js | 319 +++++--- .../test/unit/coffee/RangeManagerTests.js | 265 +++--- 5 files changed, 1512 insertions(+), 1113 deletions(-) diff --git a/services/docstore/test/unit/coffee/DocArchiveManagerTests.js b/services/docstore/test/unit/coffee/DocArchiveManagerTests.js index 70196a4b86..a6602405bd 100644 --- a/services/docstore/test/unit/coffee/DocArchiveManagerTests.js +++ b/services/docstore/test/unit/coffee/DocArchiveManagerTests.js @@ -1,356 +1,444 @@ -assert = require("chai").assert -sinon = require('sinon') -chai = require('chai') -should = chai.should() -expect = chai.expect -modulePath = "../../../app/js/DocArchiveManager.js" -SandboxedModule = require('sandboxed-module') -ObjectId = require("mongojs").ObjectId -Errors = require "../../../app/js/Errors" -crypto = require("crypto") +/* + * decaffeinate suggestions: + * DS101: Remove unnecessary use of Array.from + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +const { + assert +} = require("chai"); +const sinon = require('sinon'); +const chai = require('chai'); +const should = chai.should(); +const { + expect +} = chai; +const modulePath = "../../../app/js/DocArchiveManager.js"; +const SandboxedModule = require('sandboxed-module'); +const { + ObjectId +} = require("mongojs"); +const Errors = require("../../../app/js/Errors"); +const crypto = require("crypto"); -describe "DocArchiveManager", -> +describe("DocArchiveManager", function() { - beforeEach -> + beforeEach(function() { - @settings = - docstore: - s3: - secret: "secret" - key: "this_key" + this.settings = { + docstore: { + s3: { + secret: "secret", + key: "this_key", bucket:"doc-archive-unit-test" + } + } + }; - @request = - put: {} - get: {} + this.request = { + put: {}, + get: {}, del: {} + }; - @archivedDocs = [{ - _id: ObjectId() - inS3:true + this.archivedDocs = [{ + _id: ObjectId(), + inS3:true, rev: 2 }, { - _id: ObjectId() - inS3:true + _id: ObjectId(), + inS3:true, rev: 4 }, { - _id: ObjectId() - inS3:true + _id: ObjectId(), + inS3:true, rev: 6 - }] + }]; - @mongoDocs = [{ - _id: ObjectId() - lines: ["one", "two", "three"] + this.mongoDocs = [{ + _id: ObjectId(), + lines: ["one", "two", "three"], rev: 2 }, { - _id: ObjectId() - lines: ["aaa", "bbb", "ccc"] + _id: ObjectId(), + lines: ["aaa", "bbb", "ccc"], rev: 4 }, { - _id: ObjectId() - inS3: true + _id: ObjectId(), + inS3: true, rev: 6 }, { - _id: ObjectId() - inS3: true + _id: ObjectId(), + inS3: true, rev: 6 }, { - _id: ObjectId() - lines: ["111", "222", "333"] + _id: ObjectId(), + lines: ["111", "222", "333"], rev: 6 - }] + }]; - @unarchivedDocs = [{ - _id: ObjectId() - lines: ["wombat", "potato", "banana"] + this.unarchivedDocs = [{ + _id: ObjectId(), + lines: ["wombat", "potato", "banana"], rev: 2 }, { - _id: ObjectId() - lines: ["llama", "turnip", "apple"] + _id: ObjectId(), + lines: ["llama", "turnip", "apple"], rev: 4 }, { - _id: ObjectId() - lines: ["elephant", "swede", "nectarine"] + _id: ObjectId(), + lines: ["elephant", "swede", "nectarine"], rev: 6 - }] + }]; - @mixedDocs = @archivedDocs.concat(@unarchivedDocs) + this.mixedDocs = this.archivedDocs.concat(this.unarchivedDocs); - @MongoManager = - markDocAsArchived: sinon.stub().callsArgWith(2, null) - upsertIntoDocCollection: sinon.stub().callsArgWith(3, null) - getProjectsDocs: sinon.stub().callsArgWith(3, null, @mongoDocs) - getArchivedProjectDocs: sinon.stub().callsArgWith(2, null, @mongoDocs) + this.MongoManager = { + markDocAsArchived: sinon.stub().callsArgWith(2, null), + upsertIntoDocCollection: sinon.stub().callsArgWith(3, null), + getProjectsDocs: sinon.stub().callsArgWith(3, null, this.mongoDocs), + getArchivedProjectDocs: sinon.stub().callsArgWith(2, null, this.mongoDocs) + }; - @requires = - "settings-sharelatex": @settings - "./MongoManager": @MongoManager - "request": @request - "./RangeManager": @RangeManager = {} - "logger-sharelatex": - log:-> - err:-> - @globals = - JSON: JSON + this.requires = { + "settings-sharelatex": this.settings, + "./MongoManager": this.MongoManager, + "request": this.request, + "./RangeManager": (this.RangeManager = {}), + "logger-sharelatex": { + log() {}, + err() {} + } + }; + this.globals = + {JSON}; - @error = "my errror" - @project_id = ObjectId().toString() - @stubbedError = new Errors.NotFoundError("Error in S3 request") - @DocArchiveManager = SandboxedModule.require modulePath, requires: @requires, globals: @globals + this.error = "my errror"; + this.project_id = ObjectId().toString(); + this.stubbedError = new Errors.NotFoundError("Error in S3 request"); + return this.DocArchiveManager = SandboxedModule.require(modulePath, {requires: this.requires, globals: this.globals}); + }); - describe "archiveDoc", -> + describe("archiveDoc", function() { - it "should use correct options", (done)-> - @request.put = sinon.stub().callsArgWith(1, null, {statusCode:200,headers:{etag:""}}) - @DocArchiveManager.archiveDoc @project_id, @mongoDocs[0], (err)=> - opts = @request.put.args[0][0] - assert.deepEqual(opts.aws, {key:@settings.docstore.s3.key, secret:@settings.docstore.s3.secret, bucket:@settings.docstore.s3.bucket}) - opts.body.should.equal JSON.stringify( - lines: @mongoDocs[0].lines - ranges: @mongoDocs[0].ranges + it("should use correct options", function(done){ + this.request.put = sinon.stub().callsArgWith(1, null, {statusCode:200,headers:{etag:""}}); + return this.DocArchiveManager.archiveDoc(this.project_id, this.mongoDocs[0], err=> { + const opts = this.request.put.args[0][0]; + assert.deepEqual(opts.aws, {key:this.settings.docstore.s3.key, secret:this.settings.docstore.s3.secret, bucket:this.settings.docstore.s3.bucket}); + opts.body.should.equal(JSON.stringify({ + lines: this.mongoDocs[0].lines, + ranges: this.mongoDocs[0].ranges, schema_v: 1 - ) - opts.timeout.should.equal (30*1000) - opts.uri.should.equal "https://#{@settings.docstore.s3.bucket}.s3.amazonaws.com/#{@project_id}/#{@mongoDocs[0]._id}" - done() + }) + ); + opts.timeout.should.equal((30*1000)); + opts.uri.should.equal(`https://${this.settings.docstore.s3.bucket}.s3.amazonaws.com/${this.project_id}/${this.mongoDocs[0]._id}`); + return done(); + }); + }); - it "should return no md5 error", (done)-> - data = JSON.stringify( - lines: @mongoDocs[0].lines - ranges: @mongoDocs[0].ranges + it("should return no md5 error", function(done){ + const data = JSON.stringify({ + lines: this.mongoDocs[0].lines, + ranges: this.mongoDocs[0].ranges, schema_v: 1 - ) - @md5 = crypto.createHash("md5").update(data).digest("hex") - @request.put = sinon.stub().callsArgWith(1, null, {statusCode:200,headers:{etag:@md5}}) - @DocArchiveManager.archiveDoc @project_id, @mongoDocs[0], (err)=> - should.not.exist err - done() + }); + this.md5 = crypto.createHash("md5").update(data).digest("hex"); + this.request.put = sinon.stub().callsArgWith(1, null, {statusCode:200,headers:{etag:this.md5}}); + return this.DocArchiveManager.archiveDoc(this.project_id, this.mongoDocs[0], err=> { + should.not.exist(err); + return done(); + }); + }); - it "should return the error", (done)-> - @request.put = sinon.stub().callsArgWith(1, @stubbedError, {statusCode:400,headers:{etag:""}}) - @DocArchiveManager.archiveDoc @project_id, @mongoDocs[0], (err)=> - should.exist err - done() + return it("should return the error", function(done){ + this.request.put = sinon.stub().callsArgWith(1, this.stubbedError, {statusCode:400,headers:{etag:""}}); + return this.DocArchiveManager.archiveDoc(this.project_id, this.mongoDocs[0], err=> { + should.exist(err); + return done(); + }); + }); + }); - describe "unarchiveDoc", -> + describe("unarchiveDoc", function() { - it "should use correct options", (done)-> - @request.get = sinon.stub().callsArgWith(1, null, statusCode:200, @mongoDocs[0].lines) - @request.del = sinon.stub().callsArgWith(1, null, statusCode:204, {}) - @DocArchiveManager.unarchiveDoc @project_id, @mongoDocs[0]._id, (err)=> - opts = @request.get.args[0][0] - assert.deepEqual(opts.aws, {key:@settings.docstore.s3.key, secret:@settings.docstore.s3.secret, bucket:@settings.docstore.s3.bucket}) - opts.json.should.equal true - opts.timeout.should.equal (30*1000) - opts.uri.should.equal "https://#{@settings.docstore.s3.bucket}.s3.amazonaws.com/#{@project_id}/#{@mongoDocs[0]._id}" - done() + it("should use correct options", function(done){ + this.request.get = sinon.stub().callsArgWith(1, null, {statusCode:200}, this.mongoDocs[0].lines); + this.request.del = sinon.stub().callsArgWith(1, null, {statusCode:204}, {}); + return this.DocArchiveManager.unarchiveDoc(this.project_id, this.mongoDocs[0]._id, err=> { + const opts = this.request.get.args[0][0]; + assert.deepEqual(opts.aws, {key:this.settings.docstore.s3.key, secret:this.settings.docstore.s3.secret, bucket:this.settings.docstore.s3.bucket}); + opts.json.should.equal(true); + opts.timeout.should.equal((30*1000)); + opts.uri.should.equal(`https://${this.settings.docstore.s3.bucket}.s3.amazonaws.com/${this.project_id}/${this.mongoDocs[0]._id}`); + return done(); + }); + }); - it "should return the error", (done)-> - @request.get = sinon.stub().callsArgWith(1, @stubbedError, {}, {}) - @DocArchiveManager.unarchiveDoc @project_id, @mongoDocs[0], (err)=> - should.exist err - done() + it("should return the error", function(done){ + this.request.get = sinon.stub().callsArgWith(1, this.stubbedError, {}, {}); + return this.DocArchiveManager.unarchiveDoc(this.project_id, this.mongoDocs[0], err=> { + should.exist(err); + return done(); + }); + }); - it "should error if the doc lines are a string not an array", (done)-> - @request.get = sinon.stub().callsArgWith(1, null, statusCode:200, "this is a string") - @request.del = sinon.stub() - @DocArchiveManager.unarchiveDoc @project_id, @mongoDocs[0], (err)=> - should.exist err - @request.del.called.should.equal false - done() + return it("should error if the doc lines are a string not an array", function(done){ + this.request.get = sinon.stub().callsArgWith(1, null, {statusCode:200}, "this is a string"); + this.request.del = sinon.stub(); + return this.DocArchiveManager.unarchiveDoc(this.project_id, this.mongoDocs[0], err=> { + should.exist(err); + this.request.del.called.should.equal(false); + return done(); + }); + }); + }); - describe "archiveAllDocs", -> + describe("archiveAllDocs", function() { - it "should archive all project docs which are not in s3", (done)-> - @MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, @mongoDocs) - @DocArchiveManager.archiveDoc = sinon.stub().callsArgWith(2, null) + it("should archive all project docs which are not in s3", function(done){ + this.MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, this.mongoDocs); + this.DocArchiveManager.archiveDoc = sinon.stub().callsArgWith(2, null); - @DocArchiveManager.archiveAllDocs @project_id, (err)=> - @DocArchiveManager.archiveDoc.calledWith(@project_id, @mongoDocs[0]).should.equal true - @DocArchiveManager.archiveDoc.calledWith(@project_id, @mongoDocs[1]).should.equal true - @DocArchiveManager.archiveDoc.calledWith(@project_id, @mongoDocs[4]).should.equal true + return this.DocArchiveManager.archiveAllDocs(this.project_id, err=> { + this.DocArchiveManager.archiveDoc.calledWith(this.project_id, this.mongoDocs[0]).should.equal(true); + this.DocArchiveManager.archiveDoc.calledWith(this.project_id, this.mongoDocs[1]).should.equal(true); + this.DocArchiveManager.archiveDoc.calledWith(this.project_id, this.mongoDocs[4]).should.equal(true); - @DocArchiveManager.archiveDoc.calledWith(@project_id, @mongoDocs[2]).should.equal false - @DocArchiveManager.archiveDoc.calledWith(@project_id, @mongoDocs[3]).should.equal false + this.DocArchiveManager.archiveDoc.calledWith(this.project_id, this.mongoDocs[2]).should.equal(false); + this.DocArchiveManager.archiveDoc.calledWith(this.project_id, this.mongoDocs[3]).should.equal(false); - should.not.exist err - done() + should.not.exist(err); + return done(); + }); + }); - it "should return error if have no docs", (done)-> - @MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, null) + it("should return error if have no docs", function(done){ + this.MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, null); - @DocArchiveManager.archiveAllDocs @project_id, (err)=> - should.exist err - done() + return this.DocArchiveManager.archiveAllDocs(this.project_id, err=> { + should.exist(err); + return done(); + }); + }); - it "should return the error", (done)-> - @MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, @error, null) + it("should return the error", function(done){ + this.MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, this.error, null); - @DocArchiveManager.archiveAllDocs @project_id, (err)=> - err.should.equal @error - done() + return this.DocArchiveManager.archiveAllDocs(this.project_id, err=> { + err.should.equal(this.error); + return done(); + }); + }); - describe "when most have been already put in s3", -> + return describe("when most have been already put in s3", function() { - beforeEach -> - numberOfDocs = 10 * 1000 - @mongoDocs = [] - while --numberOfDocs != 0 - @mongoDocs.push({inS3:true, _id: ObjectId()}) + beforeEach(function() { + let numberOfDocs = 10 * 1000; + this.mongoDocs = []; + while (--numberOfDocs !== 0) { + this.mongoDocs.push({inS3:true, _id: ObjectId()}); + } - @MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, @mongoDocs) - @DocArchiveManager.archiveDoc = sinon.stub().callsArgWith(2, null) + this.MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, this.mongoDocs); + return this.DocArchiveManager.archiveDoc = sinon.stub().callsArgWith(2, null); + }); - it "should not throw and error", (done)-> - @DocArchiveManager.archiveAllDocs @project_id, (err)=> - should.not.exist err - done() + return it("should not throw and error", function(done){ + return this.DocArchiveManager.archiveAllDocs(this.project_id, err=> { + should.not.exist(err); + return done(); + }); + }); + }); + }); - describe "unArchiveAllDocs", -> + describe("unArchiveAllDocs", function() { - it "should unarchive all inS3 docs", (done)-> - @MongoManager.getArchivedProjectDocs = sinon.stub().callsArgWith(1, null, @archivedDocs) - @DocArchiveManager.unarchiveDoc = sinon.stub().callsArgWith(2, null) - @DocArchiveManager.unArchiveAllDocs @project_id, (err)=> - for doc in @archivedDocs - @DocArchiveManager.unarchiveDoc.calledWith(@project_id, doc._id).should.equal true - should.not.exist err - done() + it("should unarchive all inS3 docs", function(done){ + this.MongoManager.getArchivedProjectDocs = sinon.stub().callsArgWith(1, null, this.archivedDocs); + this.DocArchiveManager.unarchiveDoc = sinon.stub().callsArgWith(2, null); + return this.DocArchiveManager.unArchiveAllDocs(this.project_id, err=> { + for (let doc of Array.from(this.archivedDocs)) { + this.DocArchiveManager.unarchiveDoc.calledWith(this.project_id, doc._id).should.equal(true); + } + should.not.exist(err); + return done(); + }); + }); - it "should return error if have no docs", (done)-> - @MongoManager.getArchivedProjectDocs = sinon.stub().callsArgWith(1, null, null) - @DocArchiveManager.unArchiveAllDocs @project_id, (err)=> - should.exist err - done() + it("should return error if have no docs", function(done){ + this.MongoManager.getArchivedProjectDocs = sinon.stub().callsArgWith(1, null, null); + return this.DocArchiveManager.unArchiveAllDocs(this.project_id, err=> { + should.exist(err); + return done(); + }); + }); - it "should return the error", (done)-> - @MongoManager.getArchivedProjectDocs = sinon.stub().callsArgWith(1, @error, null) - @DocArchiveManager.unArchiveAllDocs @project_id, (err)=> - err.should.equal @error - done() + return it("should return the error", function(done){ + this.MongoManager.getArchivedProjectDocs = sinon.stub().callsArgWith(1, this.error, null); + return this.DocArchiveManager.unArchiveAllDocs(this.project_id, err=> { + err.should.equal(this.error); + return done(); + }); + }); + }); - describe "destroyAllDocs", -> - beforeEach -> - @request.del = sinon.stub().callsArgWith(1, null, statusCode:204, {}) - @MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, @mixedDocs) - @MongoManager.findDoc = sinon.stub().callsArgWith(3, null, null) - @MongoManager.destroyDoc = sinon.stub().yields() - for doc in @mixedDocs - @MongoManager.findDoc.withArgs(@project_id, doc._id).callsArgWith(3, null, doc) + describe("destroyAllDocs", function() { + beforeEach(function() { + this.request.del = sinon.stub().callsArgWith(1, null, {statusCode:204}, {}); + this.MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, this.mixedDocs); + this.MongoManager.findDoc = sinon.stub().callsArgWith(3, null, null); + this.MongoManager.destroyDoc = sinon.stub().yields(); + return Array.from(this.mixedDocs).map((doc) => + this.MongoManager.findDoc.withArgs(this.project_id, doc._id).callsArgWith(3, null, doc)); + }); - it "should destroy all the docs", (done)-> - @DocArchiveManager.destroyDoc = sinon.stub().callsArgWith(2, null) - @DocArchiveManager.destroyAllDocs @project_id, (err)=> - for doc in @mixedDocs - @DocArchiveManager.destroyDoc.calledWith(@project_id, doc._id).should.equal true - should.not.exist err - done() + it("should destroy all the docs", function(done){ + this.DocArchiveManager.destroyDoc = sinon.stub().callsArgWith(2, null); + return this.DocArchiveManager.destroyAllDocs(this.project_id, err=> { + for (let doc of Array.from(this.mixedDocs)) { + this.DocArchiveManager.destroyDoc.calledWith(this.project_id, doc._id).should.equal(true); + } + should.not.exist(err); + return done(); + }); + }); - it "should only the s3 docs from s3", (done)-> - docOpts = (doc) => - JSON.parse(JSON.stringify({ - aws: {key:@settings.docstore.s3.key, secret:@settings.docstore.s3.secret, bucket:@settings.docstore.s3.bucket}, + it("should only the s3 docs from s3", function(done){ + const docOpts = doc => { + return JSON.parse(JSON.stringify({ + aws: {key:this.settings.docstore.s3.key, secret:this.settings.docstore.s3.secret, bucket:this.settings.docstore.s3.bucket}, json: true, - timeout: 30 * 1000 - uri:"https://#{@settings.docstore.s3.bucket}.s3.amazonaws.com/#{@project_id}/#{doc._id}" - })) + timeout: 30 * 1000, + uri:`https://${this.settings.docstore.s3.bucket}.s3.amazonaws.com/${this.project_id}/${doc._id}` + })); + }; - @DocArchiveManager.destroyAllDocs @project_id, (err)=> - expect(err).not.to.exist + return this.DocArchiveManager.destroyAllDocs(this.project_id, err=> { + let doc; + expect(err).not.to.exist; - for doc in @archivedDocs - sinon.assert.calledWith(@request.del, docOpts(doc)) - for doc in @unarchivedDocs - expect(@request.del.calledWith(docOpts(doc))).to.equal false # no notCalledWith + for (doc of Array.from(this.archivedDocs)) { + sinon.assert.calledWith(this.request.del, docOpts(doc)); + } + for (doc of Array.from(this.unarchivedDocs)) { + expect(this.request.del.calledWith(docOpts(doc))).to.equal(false); + } // no notCalledWith - done() + return done(); + }); + }); - it "should remove the docs from mongo", (done)-> - @DocArchiveManager.destroyAllDocs @project_id, (err)=> - expect(err).not.to.exist + return it("should remove the docs from mongo", function(done){ + this.DocArchiveManager.destroyAllDocs(this.project_id, err=> { + return expect(err).not.to.exist; + }); - for doc in @mixedDocs - sinon.assert.calledWith(@MongoManager.destroyDoc, doc._id) + for (let doc of Array.from(this.mixedDocs)) { + sinon.assert.calledWith(this.MongoManager.destroyDoc, doc._id); + } - done() + return done(); + }); + }); - describe "_s3DocToMongoDoc", -> - describe "with the old schema", -> - it "should return the docs lines", (done) -> - @DocArchiveManager._s3DocToMongoDoc ["doc", "lines"], (error, doc) -> - expect(doc).to.deep.equal { - lines: ["doc", "lines"] - } - done() + describe("_s3DocToMongoDoc", function() { + describe("with the old schema", () => it("should return the docs lines", function(done) { + return this.DocArchiveManager._s3DocToMongoDoc(["doc", "lines"], function(error, doc) { + expect(doc).to.deep.equal({ + lines: ["doc", "lines"] + }); + return done(); + }); + })); - describe "with the new schema", -> - it "should return the doc lines and ranges", (done) -> - @RangeManager.jsonRangesToMongo = sinon.stub().returns {"mongo": "ranges"} - @DocArchiveManager._s3DocToMongoDoc { - lines: ["doc", "lines"] - ranges: {"json": "ranges"} + describe("with the new schema", function() { + it("should return the doc lines and ranges", function(done) { + this.RangeManager.jsonRangesToMongo = sinon.stub().returns({"mongo": "ranges"}); + return this.DocArchiveManager._s3DocToMongoDoc({ + lines: ["doc", "lines"], + ranges: {"json": "ranges"}, schema_v: 1 - }, (error, doc) -> - expect(doc).to.deep.equal { - lines: ["doc", "lines"] + }, function(error, doc) { + expect(doc).to.deep.equal({ + lines: ["doc", "lines"], ranges: {"mongo": "ranges"} - } - done() + }); + return done(); + }); + }); - it "should return just the doc lines when there are no ranges", (done) -> - @DocArchiveManager._s3DocToMongoDoc { - lines: ["doc", "lines"] + return it("should return just the doc lines when there are no ranges", function(done) { + return this.DocArchiveManager._s3DocToMongoDoc({ + lines: ["doc", "lines"], schema_v: 1 - }, (error, doc) -> - expect(doc).to.deep.equal { + }, function(error, doc) { + expect(doc).to.deep.equal({ lines: ["doc", "lines"] - } - done() + }); + return done(); + }); + }); + }); - describe "with an unrecognised schema", -> - it "should return an error", (done) -> - @DocArchiveManager._s3DocToMongoDoc { - schema_v: 2 - }, (error, doc) -> - expect(error).to.exist - done() + return describe("with an unrecognised schema", () => it("should return an error", function(done) { + return this.DocArchiveManager._s3DocToMongoDoc({ + schema_v: 2 + }, function(error, doc) { + expect(error).to.exist; + return done(); + }); + })); + }); - describe "_mongoDocToS3Doc", -> - describe "with a valid doc", -> - it "should return the json version", (done) -> - @DocArchiveManager._mongoDocToS3Doc doc = { - lines: ["doc", "lines"] - ranges: { "mock": "ranges" } - }, (err, s3_doc) -> - expect(s3_doc).to.equal JSON.stringify({ - lines: ["doc", "lines"] - ranges: { "mock": "ranges" } - schema_v: 1 - }) - done() + return describe("_mongoDocToS3Doc", function() { + describe("with a valid doc", () => it("should return the json version", function(done) { + let doc; + return this.DocArchiveManager._mongoDocToS3Doc((doc = { + lines: ["doc", "lines"], + ranges: { "mock": "ranges" } + }), function(err, s3_doc) { + expect(s3_doc).to.equal(JSON.stringify({ + lines: ["doc", "lines"], + ranges: { "mock": "ranges" }, + schema_v: 1 + }) + ); + return done(); + }); + })); - describe "with null bytes in the result", -> - beforeEach -> - @_stringify = JSON.stringify - JSON.stringify = sinon.stub().returns '{"bad": "\u0000"}' + describe("with null bytes in the result", function() { + beforeEach(function() { + this._stringify = JSON.stringify; + return JSON.stringify = sinon.stub().returns('{"bad": "\u0000"}'); + }); - afterEach -> - JSON.stringify = @_stringify + afterEach(function() { + return JSON.stringify = this._stringify; + }); - it "should return an error", (done) -> - @DocArchiveManager._mongoDocToS3Doc { - lines: ["doc", "lines"] + return it("should return an error", function(done) { + return this.DocArchiveManager._mongoDocToS3Doc({ + lines: ["doc", "lines"], ranges: { "mock": "ranges" } - }, (err, s3_doc) -> - expect(err).to.exist - done() + }, function(err, s3_doc) { + expect(err).to.exist; + return done(); + }); + }); + }); - describe "without doc lines", -> - it "should return an error", (done) -> - @DocArchiveManager._mongoDocToS3Doc {}, (err, s3_doc) -> - expect(err).to.exist - done() + return describe("without doc lines", () => it("should return an error", function(done) { + return this.DocArchiveManager._mongoDocToS3Doc({}, function(err, s3_doc) { + expect(err).to.exist; + return done(); + }); + })); + }); +}); diff --git a/services/docstore/test/unit/coffee/DocManagerTests.js b/services/docstore/test/unit/coffee/DocManagerTests.js index 70cea2e2c8..bdeb97c98d 100644 --- a/services/docstore/test/unit/coffee/DocManagerTests.js +++ b/services/docstore/test/unit/coffee/DocManagerTests.js @@ -1,407 +1,537 @@ -SandboxedModule = require('sandboxed-module') -sinon = require('sinon') -chai = require('chai') -assert = require("chai").assert -chai.should() -expect = chai.expect -modulePath = require('path').join __dirname, '../../../app/js/DocManager' -ObjectId = require("mongojs").ObjectId -Errors = require "../../../app/js/Errors" +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +const SandboxedModule = require('sandboxed-module'); +const sinon = require('sinon'); +const chai = require('chai'); +const { + assert +} = require("chai"); +chai.should(); +const { + expect +} = chai; +const modulePath = require('path').join(__dirname, '../../../app/js/DocManager'); +const { + ObjectId +} = require("mongojs"); +const Errors = require("../../../app/js/Errors"); -describe "DocManager", -> - beforeEach -> - @DocManager = SandboxedModule.require modulePath, requires: - "./MongoManager": @MongoManager = {} - "./DocArchiveManager": @DocArchiveManager = {} - "./RangeManager": @RangeManager = { - jsonRangesToMongo: (r) -> r - shouldUpdateRanges: sinon.stub().returns false - } - "logger-sharelatex": @logger = - log: sinon.stub() - warn:-> - err:-> - @doc_id = ObjectId().toString() - @project_id = ObjectId().toString() - @another_project_id = ObjectId().toString() - @callback = sinon.stub() - @stubbedError = new Error("blew up") +describe("DocManager", function() { + beforeEach(function() { + this.DocManager = SandboxedModule.require(modulePath, { requires: { + "./MongoManager": (this.MongoManager = {}), + "./DocArchiveManager": (this.DocArchiveManager = {}), + "./RangeManager": (this.RangeManager = { + jsonRangesToMongo(r) { return r; }, + shouldUpdateRanges: sinon.stub().returns(false) + }), + "logger-sharelatex": (this.logger = { + log: sinon.stub(), + warn() {}, + err() {} + }) + } + } + ); + this.doc_id = ObjectId().toString(); + this.project_id = ObjectId().toString(); + this.another_project_id = ObjectId().toString(); + this.callback = sinon.stub(); + return this.stubbedError = new Error("blew up"); + }); - describe "checkDocExists", -> - beforeEach -> - @DocManager._getDoc = sinon.stub() + describe("checkDocExists", function() { + beforeEach(function() { + return this.DocManager._getDoc = sinon.stub(); + }); - it "should call get doc with a quick filter", (done)-> - @DocManager._getDoc.callsArgWith(3, null, {_id:@doc_id}) - @DocManager.checkDocExists @project_id, @doc_id, (err, exist)=> - exist.should.equal true - @DocManager._getDoc.calledWith(@project_id, @doc_id, {_id:1, inS3:true}).should.equal true - done() + it("should call get doc with a quick filter", function(done){ + this.DocManager._getDoc.callsArgWith(3, null, {_id:this.doc_id}); + return this.DocManager.checkDocExists(this.project_id, this.doc_id, (err, exist)=> { + exist.should.equal(true); + this.DocManager._getDoc.calledWith(this.project_id, this.doc_id, {_id:1, inS3:true}).should.equal(true); + return done(); + }); + }); - it "should return false when doc is not there", (done)-> - @DocManager._getDoc.callsArgWith(3, null) - @DocManager.checkDocExists @project_id, @doc_id, (err, exist)=> - exist.should.equal false - done() + it("should return false when doc is not there", function(done){ + this.DocManager._getDoc.callsArgWith(3, null); + return this.DocManager.checkDocExists(this.project_id, this.doc_id, (err, exist)=> { + exist.should.equal(false); + return done(); + }); + }); - it "should return error when get doc errors", (done)-> - @DocManager._getDoc.callsArgWith(3, "error") - @DocManager.checkDocExists @project_id, @doc_id, (err, exist)=> - err.should.equal "error" - done() + return it("should return error when get doc errors", function(done){ + this.DocManager._getDoc.callsArgWith(3, "error"); + return this.DocManager.checkDocExists(this.project_id, this.doc_id, (err, exist)=> { + err.should.equal("error"); + return done(); + }); + }); + }); - describe "getFullDoc", -> - beforeEach -> - @DocManager._getDoc = sinon.stub() - @doc = - _id: @doc_id + describe("getFullDoc", function() { + beforeEach(function() { + this.DocManager._getDoc = sinon.stub(); + return this.doc = { + _id: this.doc_id, lines:["2134"] + };}); - it "should call get doc with a quick filter", (done)-> - @DocManager._getDoc.callsArgWith(3, null, @doc) - @DocManager.getFullDoc @project_id, @doc_id, (err, doc)=> - doc.should.equal @doc - @DocManager._getDoc.calledWith(@project_id, @doc_id, {lines: true, rev: true, deleted: true, version: true, ranges: true, inS3:true}).should.equal true - done() + it("should call get doc with a quick filter", function(done){ + this.DocManager._getDoc.callsArgWith(3, null, this.doc); + return this.DocManager.getFullDoc(this.project_id, this.doc_id, (err, doc)=> { + doc.should.equal(this.doc); + this.DocManager._getDoc.calledWith(this.project_id, this.doc_id, {lines: true, rev: true, deleted: true, version: true, ranges: true, inS3:true}).should.equal(true); + return done(); + }); + }); - it "should return error when get doc errors", (done)-> - @DocManager._getDoc.callsArgWith(3, "error") - @DocManager.getFullDoc @project_id, @doc_id, (err, exist)=> - err.should.equal "error" - done() + return it("should return error when get doc errors", function(done){ + this.DocManager._getDoc.callsArgWith(3, "error"); + return this.DocManager.getFullDoc(this.project_id, this.doc_id, (err, exist)=> { + err.should.equal("error"); + return done(); + }); + }); + }); - describe "getRawDoc", -> + describe("getRawDoc", function() { - beforeEach -> - @DocManager._getDoc = sinon.stub() - @doc = - lines:["2134"] + beforeEach(function() { + this.DocManager._getDoc = sinon.stub(); + return this.doc = + {lines:["2134"]};}); - it "should call get doc with a quick filter", (done)-> - @DocManager._getDoc.callsArgWith(3, null, @doc) - @DocManager.getDocLines @project_id, @doc_id, (err, doc)=> - doc.should.equal @doc - @DocManager._getDoc.calledWith(@project_id, @doc_id, {lines: true, inS3:true}).should.equal true - done() + it("should call get doc with a quick filter", function(done){ + this.DocManager._getDoc.callsArgWith(3, null, this.doc); + return this.DocManager.getDocLines(this.project_id, this.doc_id, (err, doc)=> { + doc.should.equal(this.doc); + this.DocManager._getDoc.calledWith(this.project_id, this.doc_id, {lines: true, inS3:true}).should.equal(true); + return done(); + }); + }); - it "should return error when get doc errors", (done)-> - @DocManager._getDoc.callsArgWith(3, "error") - @DocManager.getDocLines @project_id, @doc_id, (err, exist)=> - err.should.equal "error" - done() + return it("should return error when get doc errors", function(done){ + this.DocManager._getDoc.callsArgWith(3, "error"); + return this.DocManager.getDocLines(this.project_id, this.doc_id, (err, exist)=> { + err.should.equal("error"); + return done(); + }); + }); + }); - describe "getDoc", -> - beforeEach -> - @project = { name: "mock-project" } - @doc = { _id: @doc_id, project_id: @project_id, lines: ["mock-lines"] } - @version = 42 - @MongoManager.findDoc = sinon.stub() - @MongoManager.getDocVersion = sinon.stub().yields(null, @version) + describe("getDoc", function() { + beforeEach(function() { + this.project = { name: "mock-project" }; + this.doc = { _id: this.doc_id, project_id: this.project_id, lines: ["mock-lines"] }; + this.version = 42; + this.MongoManager.findDoc = sinon.stub(); + return this.MongoManager.getDocVersion = sinon.stub().yields(null, this.version); + }); - describe "when using a filter", -> - beforeEach -> - @MongoManager.findDoc.yields(null, @doc) + describe("when using a filter", function() { + beforeEach(function() { + return this.MongoManager.findDoc.yields(null, this.doc); + }); - it "should error if inS3 is not set to true", (done)-> - @DocManager._getDoc @project_id, @doc_id, {inS3: false}, (err)-> - expect(err).to.exist - done() + it("should error if inS3 is not set to true", function(done){ + return this.DocManager._getDoc(this.project_id, this.doc_id, {inS3: false}, function(err){ + expect(err).to.exist; + return done(); + }); + }); - it "should always get inS3 even when no filter is passed", (done)-> - @DocManager._getDoc @project_id, @doc_id, undefined, (err)=> - @MongoManager.findDoc.called.should.equal false - expect(err).to.exist - done() + it("should always get inS3 even when no filter is passed", function(done){ + return this.DocManager._getDoc(this.project_id, this.doc_id, undefined, err=> { + this.MongoManager.findDoc.called.should.equal(false); + expect(err).to.exist; + return done(); + }); + }); - it "should not error if inS3 is set to true", (done)-> - @DocManager._getDoc @project_id, @doc_id, {inS3: true}, (err)-> - expect(err).to.not.exist - done() + return it("should not error if inS3 is set to true", function(done){ + return this.DocManager._getDoc(this.project_id, this.doc_id, {inS3: true}, function(err){ + expect(err).to.not.exist; + return done(); + }); + }); + }); - describe "when the doc is in the doc collection", -> - beforeEach -> - @MongoManager.findDoc.yields(null, @doc) - @DocManager._getDoc @project_id, @doc_id, {version: true, inS3:true}, @callback + describe("when the doc is in the doc collection", function() { + beforeEach(function() { + this.MongoManager.findDoc.yields(null, this.doc); + return this.DocManager._getDoc(this.project_id, this.doc_id, {version: true, inS3:true}, this.callback); + }); - it "should get the doc from the doc collection", -> - @MongoManager.findDoc - .calledWith(@project_id, @doc_id) - .should.equal true + it("should get the doc from the doc collection", function() { + return this.MongoManager.findDoc + .calledWith(this.project_id, this.doc_id) + .should.equal(true); + }); - it "should get the doc version from the docOps collection", -> - @MongoManager.getDocVersion - .calledWith(@doc_id) - .should.equal true + it("should get the doc version from the docOps collection", function() { + return this.MongoManager.getDocVersion + .calledWith(this.doc_id) + .should.equal(true); + }); - it "should return the callback with the doc with the version", -> - @callback.called.should.equal true - doc = @callback.args[0][1] - doc.lines.should.equal @doc.lines - doc.version.should.equal @version + return it("should return the callback with the doc with the version", function() { + this.callback.called.should.equal(true); + const doc = this.callback.args[0][1]; + doc.lines.should.equal(this.doc.lines); + return doc.version.should.equal(this.version); + }); + }); - describe "without the version filter", -> - beforeEach -> - @MongoManager.findDoc.yields(null, @doc) - @DocManager._getDoc @project_id, @doc_id, {version: false, inS3:true}, @callback + describe("without the version filter", function() { + beforeEach(function() { + this.MongoManager.findDoc.yields(null, this.doc); + return this.DocManager._getDoc(this.project_id, this.doc_id, {version: false, inS3:true}, this.callback); + }); - it "should not get the doc version from the docOps collection", -> - @MongoManager.getDocVersion.called.should.equal false + return it("should not get the doc version from the docOps collection", function() { + return this.MongoManager.getDocVersion.called.should.equal(false); + }); + }); - describe "when MongoManager.findDoc errors", -> - beforeEach -> - @MongoManager.findDoc.yields(@stubbedError) - @DocManager._getDoc @project_id, @doc_id, {version: true, inS3:true}, @callback + describe("when MongoManager.findDoc errors", function() { + beforeEach(function() { + this.MongoManager.findDoc.yields(this.stubbedError); + return this.DocManager._getDoc(this.project_id, this.doc_id, {version: true, inS3:true}, this.callback); + }); - it "should return the error", -> - @callback.calledWith(@stubbedError).should.equal true + return it("should return the error", function() { + return this.callback.calledWith(this.stubbedError).should.equal(true); + }); + }); - describe "when the doc is archived", -> - beforeEach -> - @doc = { _id: @doc_id, project_id: @project_id, lines: ["mock-lines"], inS3: true } - @MongoManager.findDoc.yields(null, @doc) - @DocArchiveManager.unarchiveDoc = (project_id, doc_id, callback) => - @doc.inS3 = false - callback() - sinon.spy @DocArchiveManager, "unarchiveDoc" - @DocManager._getDoc @project_id, @doc_id, {version: true, inS3:true}, @callback + describe("when the doc is archived", function() { + beforeEach(function() { + this.doc = { _id: this.doc_id, project_id: this.project_id, lines: ["mock-lines"], inS3: true }; + this.MongoManager.findDoc.yields(null, this.doc); + this.DocArchiveManager.unarchiveDoc = (project_id, doc_id, callback) => { + this.doc.inS3 = false; + return callback(); + }; + sinon.spy(this.DocArchiveManager, "unarchiveDoc"); + return this.DocManager._getDoc(this.project_id, this.doc_id, {version: true, inS3:true}, this.callback); + }); - it "should call the DocArchive to unarchive the doc", -> - @DocArchiveManager.unarchiveDoc.calledWith(@project_id, @doc_id).should.equal true + it("should call the DocArchive to unarchive the doc", function() { + return this.DocArchiveManager.unarchiveDoc.calledWith(this.project_id, this.doc_id).should.equal(true); + }); - it "should look up the doc twice", -> - @MongoManager.findDoc.calledTwice.should.equal true + it("should look up the doc twice", function() { + return this.MongoManager.findDoc.calledTwice.should.equal(true); + }); - it "should return the doc", -> - @callback.calledWith(null, @doc).should.equal true + return it("should return the doc", function() { + return this.callback.calledWith(null, this.doc).should.equal(true); + }); + }); - describe "when the doc does not exist in the docs collection", -> - beforeEach -> - @MongoManager.findDoc = sinon.stub().yields(null, null) - @DocManager._getDoc @project_id, @doc_id, {version: true, inS3:true}, @callback + return describe("when the doc does not exist in the docs collection", function() { + beforeEach(function() { + this.MongoManager.findDoc = sinon.stub().yields(null, null); + return this.DocManager._getDoc(this.project_id, this.doc_id, {version: true, inS3:true}, this.callback); + }); - it "should return a NotFoundError", -> - @callback - .calledWith(sinon.match.has('message', "No such doc: #{@doc_id} in project #{@project_id}")) - .should.equal true + return it("should return a NotFoundError", function() { + return this.callback + .calledWith(sinon.match.has('message', `No such doc: ${this.doc_id} in project ${this.project_id}`)) + .should.equal(true); + }); + }); + }); - describe "getAllNonDeletedDocs", -> - describe "when the project exists", -> - beforeEach -> - @docs = [{ _id: @doc_id, project_id: @project_id, lines: ["mock-lines"] }] - @MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, @docs) - @DocArchiveManager.unArchiveAllDocs = sinon.stub().callsArgWith(1, null, @docs) - @filter = { lines: true } - @DocManager.getAllNonDeletedDocs @project_id, @filter, @callback + describe("getAllNonDeletedDocs", function() { + describe("when the project exists", function() { + beforeEach(function() { + this.docs = [{ _id: this.doc_id, project_id: this.project_id, lines: ["mock-lines"] }]; + this.MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, this.docs); + this.DocArchiveManager.unArchiveAllDocs = sinon.stub().callsArgWith(1, null, this.docs); + this.filter = { lines: true }; + return this.DocManager.getAllNonDeletedDocs(this.project_id, this.filter, this.callback); + }); - it "should get the project from the database", -> - @MongoManager.getProjectsDocs - .calledWith(@project_id, {include_deleted: false}, @filter) - .should.equal true + it("should get the project from the database", function() { + return this.MongoManager.getProjectsDocs + .calledWith(this.project_id, {include_deleted: false}, this.filter) + .should.equal(true); + }); - it "should return the docs", -> - @callback.calledWith(null, @docs).should.equal true + return it("should return the docs", function() { + return this.callback.calledWith(null, this.docs).should.equal(true); + }); + }); - describe "when there are no docs for the project", -> - beforeEach -> - @MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, null) - @DocArchiveManager.unArchiveAllDocs = sinon.stub().callsArgWith(1, null) - @DocManager.getAllNonDeletedDocs @project_id, @filter, @callback + return describe("when there are no docs for the project", function() { + beforeEach(function() { + this.MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, null); + this.DocArchiveManager.unArchiveAllDocs = sinon.stub().callsArgWith(1, null); + return this.DocManager.getAllNonDeletedDocs(this.project_id, this.filter, this.callback); + }); - it "should return a NotFoundError", -> - @callback - .calledWith(sinon.match.has('message', "No docs for project #{@project_id}")) - .should.equal true + return it("should return a NotFoundError", function() { + return this.callback + .calledWith(sinon.match.has('message', `No docs for project ${this.project_id}`)) + .should.equal(true); + }); + }); + }); - describe "deleteDoc", -> - describe "when the doc exists", -> - beforeEach -> - @lines = ["mock", "doc", "lines"] - @rev = 77 - @DocManager.checkDocExists = sinon.stub().callsArgWith(2, null, true) - @MongoManager.markDocAsDeleted = sinon.stub().callsArg(2) - @DocManager.deleteDoc @project_id, @doc_id, @callback + describe("deleteDoc", function() { + describe("when the doc exists", function() { + beforeEach(function() { + this.lines = ["mock", "doc", "lines"]; + this.rev = 77; + this.DocManager.checkDocExists = sinon.stub().callsArgWith(2, null, true); + this.MongoManager.markDocAsDeleted = sinon.stub().callsArg(2); + return this.DocManager.deleteDoc(this.project_id, this.doc_id, this.callback); + }); - it "should get the doc", -> - @DocManager.checkDocExists - .calledWith(@project_id, @doc_id) - .should.equal true + it("should get the doc", function() { + return this.DocManager.checkDocExists + .calledWith(this.project_id, this.doc_id) + .should.equal(true); + }); - it "should mark doc as deleted", -> - @MongoManager.markDocAsDeleted - .calledWith(@project_id, @doc_id) - .should.equal true + it("should mark doc as deleted", function() { + return this.MongoManager.markDocAsDeleted + .calledWith(this.project_id, this.doc_id) + .should.equal(true); + }); - it "should return the callback", -> - @callback.called.should.equal true + return it("should return the callback", function() { + return this.callback.called.should.equal(true); + }); + }); - describe "when the doc does not exist", -> - beforeEach -> - @DocManager.checkDocExists = sinon.stub().callsArgWith(2, null, false) - @DocManager.deleteDoc @project_id, @doc_id, @callback + return describe("when the doc does not exist", function() { + beforeEach(function() { + this.DocManager.checkDocExists = sinon.stub().callsArgWith(2, null, false); + return this.DocManager.deleteDoc(this.project_id, this.doc_id, this.callback); + }); - it "should return a NotFoundError", -> - @callback - .calledWith(sinon.match.has('message', "No such project/doc to delete: #{@project_id}/#{@doc_id}")) - .should.equal true + return it("should return a NotFoundError", function() { + return this.callback + .calledWith(sinon.match.has('message', `No such project/doc to delete: ${this.project_id}/${this.doc_id}`)) + .should.equal(true); + }); + }); + }); - describe "updateDoc", -> - beforeEach -> - @oldDocLines = ["old", "doc", "lines"] - @newDocLines = ["new", "doc", "lines"] - @originalRanges = { + return describe("updateDoc", function() { + beforeEach(function() { + this.oldDocLines = ["old", "doc", "lines"]; + this.newDocLines = ["new", "doc", "lines"]; + this.originalRanges = { changes: [{ - id: ObjectId().toString() - op: { i: "foo", p: 3 } - meta: - user_id: ObjectId().toString() + id: ObjectId().toString(), + op: { i: "foo", p: 3 }, + meta: { + user_id: ObjectId().toString(), ts: new Date().toString() + } }] - } - @newRanges = { + }; + this.newRanges = { changes: [{ - id: ObjectId().toString() - op: { i: "bar", p: 6 } - meta: - user_id: ObjectId().toString() + id: ObjectId().toString(), + op: { i: "bar", p: 6 }, + meta: { + user_id: ObjectId().toString(), ts: new Date().toString() + } }] - } - @version = 42 - @doc = { _id: @doc_id, project_id: @project_id, lines: @oldDocLines, rev: @rev = 5, version: @version, ranges: @originalRanges } + }; + this.version = 42; + this.doc = { _id: this.doc_id, project_id: this.project_id, lines: this.oldDocLines, rev: (this.rev = 5), version: this.version, ranges: this.originalRanges }; - @MongoManager.upsertIntoDocCollection = sinon.stub().callsArg(3) - @MongoManager.setDocVersion = sinon.stub().yields() - @DocManager._getDoc = sinon.stub() + this.MongoManager.upsertIntoDocCollection = sinon.stub().callsArg(3); + this.MongoManager.setDocVersion = sinon.stub().yields(); + return this.DocManager._getDoc = sinon.stub(); + }); - describe "when only the doc lines have changed", -> - beforeEach -> - @DocManager._getDoc = sinon.stub().callsArgWith(3, null, @doc) - @DocManager.updateDoc @project_id, @doc_id, @newDocLines, @version, @originalRanges, @callback + describe("when only the doc lines have changed", function() { + beforeEach(function() { + this.DocManager._getDoc = sinon.stub().callsArgWith(3, null, this.doc); + return this.DocManager.updateDoc(this.project_id, this.doc_id, this.newDocLines, this.version, this.originalRanges, this.callback); + }); - it "should get the existing doc", -> - @DocManager._getDoc - .calledWith(@project_id, @doc_id, {version: true, rev: true, lines: true, version: true, ranges: true, inS3:true}) - .should.equal true + it("should get the existing doc", function() { + return this.DocManager._getDoc + .calledWith(this.project_id, this.doc_id, {version: true, rev: true, lines: true, version: true, ranges: true, inS3:true}) + .should.equal(true); + }); - it "should upsert the document to the doc collection", -> - @MongoManager.upsertIntoDocCollection - .calledWith(@project_id, @doc_id, {lines: @newDocLines}) - .should.equal true + it("should upsert the document to the doc collection", function() { + return this.MongoManager.upsertIntoDocCollection + .calledWith(this.project_id, this.doc_id, {lines: this.newDocLines}) + .should.equal(true); + }); - it "should not update the version", -> - @MongoManager.setDocVersion.called.should.equal false + it("should not update the version", function() { + return this.MongoManager.setDocVersion.called.should.equal(false); + }); - it "should return the callback with the new rev", -> - @callback.calledWith(null, true, @rev + 1).should.equal true + return it("should return the callback with the new rev", function() { + return this.callback.calledWith(null, true, this.rev + 1).should.equal(true); + }); + }); - describe "when the doc ranges have changed", -> - beforeEach -> - @DocManager._getDoc = sinon.stub().callsArgWith(3, null, @doc) - @RangeManager.shouldUpdateRanges.returns true - @DocManager.updateDoc @project_id, @doc_id, @oldDocLines, @version, @newRanges, @callback + describe("when the doc ranges have changed", function() { + beforeEach(function() { + this.DocManager._getDoc = sinon.stub().callsArgWith(3, null, this.doc); + this.RangeManager.shouldUpdateRanges.returns(true); + return this.DocManager.updateDoc(this.project_id, this.doc_id, this.oldDocLines, this.version, this.newRanges, this.callback); + }); - it "should upsert the ranges", -> - @MongoManager.upsertIntoDocCollection - .calledWith(@project_id, @doc_id, {ranges: @newRanges}) - .should.equal true + it("should upsert the ranges", function() { + return this.MongoManager.upsertIntoDocCollection + .calledWith(this.project_id, this.doc_id, {ranges: this.newRanges}) + .should.equal(true); + }); - it "should not update the version", -> - @MongoManager.setDocVersion.called.should.equal false + it("should not update the version", function() { + return this.MongoManager.setDocVersion.called.should.equal(false); + }); - it "should return the callback with the new rev", -> - @callback.calledWith(null, true, @rev + 1).should.equal true + return it("should return the callback with the new rev", function() { + return this.callback.calledWith(null, true, this.rev + 1).should.equal(true); + }); + }); - describe "when only the version has changed", -> - beforeEach -> - @DocManager._getDoc = sinon.stub().callsArgWith(3, null, @doc) - @DocManager.updateDoc @project_id, @doc_id, @oldDocLines, @version + 1, @originalRanges, @callback + describe("when only the version has changed", function() { + beforeEach(function() { + this.DocManager._getDoc = sinon.stub().callsArgWith(3, null, this.doc); + return this.DocManager.updateDoc(this.project_id, this.doc_id, this.oldDocLines, this.version + 1, this.originalRanges, this.callback); + }); - it "should not change the lines or ranges", -> - @MongoManager.upsertIntoDocCollection.called.should.equal false + it("should not change the lines or ranges", function() { + return this.MongoManager.upsertIntoDocCollection.called.should.equal(false); + }); - it "should update the version", -> - @MongoManager.setDocVersion - .calledWith(@doc_id, @version + 1) - .should.equal true + it("should update the version", function() { + return this.MongoManager.setDocVersion + .calledWith(this.doc_id, this.version + 1) + .should.equal(true); + }); - it "should return the callback with the old rev", -> - @callback.calledWith(null, true, @rev).should.equal true + return it("should return the callback with the old rev", function() { + return this.callback.calledWith(null, true, this.rev).should.equal(true); + }); + }); - describe "when the doc has not changed at all", -> - beforeEach -> - @DocManager._getDoc = sinon.stub().callsArgWith(3, null, @doc) - @DocManager.updateDoc @project_id, @doc_id, @oldDocLines, @version, @originalRanges, @callback + describe("when the doc has not changed at all", function() { + beforeEach(function() { + this.DocManager._getDoc = sinon.stub().callsArgWith(3, null, this.doc); + return this.DocManager.updateDoc(this.project_id, this.doc_id, this.oldDocLines, this.version, this.originalRanges, this.callback); + }); - it "should not update the ranges or lines", -> - @MongoManager.upsertIntoDocCollection.called.should.equal false + it("should not update the ranges or lines", function() { + return this.MongoManager.upsertIntoDocCollection.called.should.equal(false); + }); - it "should not update the version", -> - @MongoManager.setDocVersion.called.should.equal false + it("should not update the version", function() { + return this.MongoManager.setDocVersion.called.should.equal(false); + }); - it "should return the callback with the old rev and modified == false", -> - @callback.calledWith(null, false, @rev).should.equal true + return it("should return the callback with the old rev and modified == false", function() { + return this.callback.calledWith(null, false, this.rev).should.equal(true); + }); + }); - describe "when the version is null", -> - beforeEach -> - @DocManager.updateDoc @project_id, @doc_id, @newDocLines, null, @originalRanges, @callback + describe("when the version is null", function() { + beforeEach(function() { + return this.DocManager.updateDoc(this.project_id, this.doc_id, this.newDocLines, null, this.originalRanges, this.callback); + }); - it "should return an error", -> - @callback.calledWith(sinon.match.has('message', "no lines, version or ranges provided")).should.equal true + return it("should return an error", function() { + return this.callback.calledWith(sinon.match.has('message', "no lines, version or ranges provided")).should.equal(true); + }); + }); - describe "when the lines are null", -> - beforeEach -> - @DocManager.updateDoc @project_id, @doc_id, null, @version, @originalRanges, @callback + describe("when the lines are null", function() { + beforeEach(function() { + return this.DocManager.updateDoc(this.project_id, this.doc_id, null, this.version, this.originalRanges, this.callback); + }); - it "should return an error", -> - @callback.calledWith(sinon.match.has('message', "no lines, version or ranges provided")).should.equal true + return it("should return an error", function() { + return this.callback.calledWith(sinon.match.has('message', "no lines, version or ranges provided")).should.equal(true); + }); + }); - describe "when the ranges are null", -> - beforeEach -> - @DocManager.updateDoc @project_id, @doc_id, @newDocLines, @version, null, @callback + describe("when the ranges are null", function() { + beforeEach(function() { + return this.DocManager.updateDoc(this.project_id, this.doc_id, this.newDocLines, this.version, null, this.callback); + }); - it "should return an error", -> - @callback.calledWith(sinon.match.has('message', "no lines, version or ranges provided")).should.equal true + return it("should return an error", function() { + return this.callback.calledWith(sinon.match.has('message', "no lines, version or ranges provided")).should.equal(true); + }); + }); - describe "when there is a generic error getting the doc", -> - beforeEach -> - @error = new Error("doc could not be found") - @DocManager._getDoc = sinon.stub().callsArgWith(3, @error, null, null) - @DocManager.updateDoc @project_id, @doc_id, @newDocLines, @version, @originalRanges, @callback + describe("when there is a generic error getting the doc", function() { + beforeEach(function() { + this.error = new Error("doc could not be found"); + this.DocManager._getDoc = sinon.stub().callsArgWith(3, this.error, null, null); + return this.DocManager.updateDoc(this.project_id, this.doc_id, this.newDocLines, this.version, this.originalRanges, this.callback); + }); - it "should not upsert the document to the doc collection", -> - @MongoManager.upsertIntoDocCollection.called.should.equal false + it("should not upsert the document to the doc collection", function() { + return this.MongoManager.upsertIntoDocCollection.called.should.equal(false); + }); - it "should return the callback with the error", -> - @callback.calledWith(@error).should.equal true + return it("should return the callback with the error", function() { + return this.callback.calledWith(this.error).should.equal(true); + }); + }); - describe "when the doc lines have not changed", -> - beforeEach -> - @DocManager._getDoc = sinon.stub().callsArgWith(3, null, @doc) - @DocManager.updateDoc @project_id, @doc_id, @oldDocLines.slice(), @version, @originalRanges, @callback + describe("when the doc lines have not changed", function() { + beforeEach(function() { + this.DocManager._getDoc = sinon.stub().callsArgWith(3, null, this.doc); + return this.DocManager.updateDoc(this.project_id, this.doc_id, this.oldDocLines.slice(), this.version, this.originalRanges, this.callback); + }); - it "should not update the doc", -> - @MongoManager.upsertIntoDocCollection.called.should.equal false + it("should not update the doc", function() { + return this.MongoManager.upsertIntoDocCollection.called.should.equal(false); + }); - it "should return the callback with the existing rev", -> - @callback.calledWith(null, false, @rev).should.equal true + return it("should return the callback with the existing rev", function() { + return this.callback.calledWith(null, false, this.rev).should.equal(true); + }); + }); - describe "when the doc does not exist", -> - beforeEach -> - @DocManager._getDoc = sinon.stub().callsArgWith(3, null, null, null) - @DocManager.updateDoc @project_id, @doc_id, @newDocLines, @version, @originalRanges, @callback + return describe("when the doc does not exist", function() { + beforeEach(function() { + this.DocManager._getDoc = sinon.stub().callsArgWith(3, null, null, null); + return this.DocManager.updateDoc(this.project_id, this.doc_id, this.newDocLines, this.version, this.originalRanges, this.callback); + }); - it "should upsert the document to the doc collection", -> - @MongoManager.upsertIntoDocCollection - .calledWith(@project_id, @doc_id, {lines: @newDocLines, ranges: @originalRanges}) - .should.equal true + it("should upsert the document to the doc collection", function() { + return this.MongoManager.upsertIntoDocCollection + .calledWith(this.project_id, this.doc_id, {lines: this.newDocLines, ranges: this.originalRanges}) + .should.equal(true); + }); - it "should set the version", -> - @MongoManager.setDocVersion - .calledWith(@doc_id, @version) - .should.equal true + it("should set the version", function() { + return this.MongoManager.setDocVersion + .calledWith(this.doc_id, this.version) + .should.equal(true); + }); - it "should return the callback with the new rev", -> - @callback.calledWith(null, true, 1).should.equal true + return it("should return the callback with the new rev", function() { + return this.callback.calledWith(null, true, 1).should.equal(true); + }); + }); + }); +}); diff --git a/services/docstore/test/unit/coffee/HttpControllerTests.js b/services/docstore/test/unit/coffee/HttpControllerTests.js index 3b7ffbbe8d..615ed5c798 100644 --- a/services/docstore/test/unit/coffee/HttpControllerTests.js +++ b/services/docstore/test/unit/coffee/HttpControllerTests.js @@ -1,357 +1,444 @@ -SandboxedModule = require('sandboxed-module') -assert = require("chai").assert -sinon = require('sinon') -chai = require('chai') -chai.should() -expect = chai.expect -modulePath = require('path').join __dirname, '../../../app/js/HttpController' -ObjectId = require("mongojs").ObjectId +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +const SandboxedModule = require('sandboxed-module'); +const { + assert +} = require("chai"); +const sinon = require('sinon'); +const chai = require('chai'); +chai.should(); +const { + expect +} = chai; +const modulePath = require('path').join(__dirname, '../../../app/js/HttpController'); +const { + ObjectId +} = require("mongojs"); -describe "HttpController", -> - beforeEach -> - @HttpController = SandboxedModule.require modulePath, requires: - "./DocManager": @DocManager = {} - "./DocArchiveManager": @DocArchiveManager = {} - "logger-sharelatex": @logger = { log: sinon.stub(), error: sinon.stub() } +describe("HttpController", function() { + beforeEach(function() { + this.HttpController = SandboxedModule.require(modulePath, { requires: { + "./DocManager": (this.DocManager = {}), + "./DocArchiveManager": (this.DocArchiveManager = {}), + "logger-sharelatex": (this.logger = { log: sinon.stub(), error: sinon.stub() }), "./HealthChecker": {} - @res = { send: sinon.stub(), json: sinon.stub(), setHeader:sinon.stub() } - @res.status = sinon.stub().returns(@res) - @req = { query:{}} - @next = sinon.stub() - @project_id = "mock-project-id" - @doc_id = "mock-doc-id" - @doc = { - _id: @doc_id - lines: ["mock", "lines", " here", "", "", " spaces "] - version: 42 - rev: 5 } - @deletedDoc = { - deleted:true - _id: @doc_id - lines: ["mock", "lines", " here", "", "", " spaces "] - version: 42 + }); + this.res = { send: sinon.stub(), json: sinon.stub(), setHeader:sinon.stub() }; + this.res.status = sinon.stub().returns(this.res); + this.req = { query:{}}; + this.next = sinon.stub(); + this.project_id = "mock-project-id"; + this.doc_id = "mock-doc-id"; + this.doc = { + _id: this.doc_id, + lines: ["mock", "lines", " here", "", "", " spaces "], + version: 42, rev: 5 - } + }; + return this.deletedDoc = { + deleted:true, + _id: this.doc_id, + lines: ["mock", "lines", " here", "", "", " spaces "], + version: 42, + rev: 5 + };}); - describe "getDoc", -> + describe("getDoc", function() { - describe "without deleted docs", -> - beforeEach -> - @req.params = - project_id: @project_id - doc_id: @doc_id - @DocManager.getFullDoc = sinon.stub().callsArgWith(2, null, @doc) - @HttpController.getDoc @req, @res, @next + describe("without deleted docs", function() { + beforeEach(function() { + this.req.params = { + project_id: this.project_id, + doc_id: this.doc_id + }; + this.DocManager.getFullDoc = sinon.stub().callsArgWith(2, null, this.doc); + return this.HttpController.getDoc(this.req, this.res, this.next); + }); - it "should get the document with the version (including deleted)", -> - @DocManager.getFullDoc - .calledWith(@project_id, @doc_id) - .should.equal true + it("should get the document with the version (including deleted)", function() { + return this.DocManager.getFullDoc + .calledWith(this.project_id, this.doc_id) + .should.equal(true); + }); - it "should return the doc as JSON", -> - @res.json + return it("should return the doc as JSON", function() { + return this.res.json .calledWith({ - _id: @doc_id - lines: @doc.lines - rev: @doc.rev - version: @doc.version + _id: this.doc_id, + lines: this.doc.lines, + rev: this.doc.rev, + version: this.doc.version }) - .should.equal true + .should.equal(true); + }); + }); - describe "which is deleted", -> - beforeEach -> - @req.params = - project_id: @project_id - doc_id: @doc_id - @DocManager.getFullDoc = sinon.stub().callsArgWith(2, null, @deletedDoc) + return describe("which is deleted", function() { + beforeEach(function() { + this.req.params = { + project_id: this.project_id, + doc_id: this.doc_id + }; + return this.DocManager.getFullDoc = sinon.stub().callsArgWith(2, null, this.deletedDoc); + }); - it "should get the doc from the doc manager", -> - @HttpController.getDoc @req, @res, @next - @DocManager.getFullDoc.calledWith(@project_id, @doc_id).should.equal true + it("should get the doc from the doc manager", function() { + this.HttpController.getDoc(this.req, this.res, this.next); + return this.DocManager.getFullDoc.calledWith(this.project_id, this.doc_id).should.equal(true); + }); - it "should return 404 if the query string delete is not set ", -> - @HttpController.getDoc @req, @res, @next - @res.send.calledWith(404).should.equal true + it("should return 404 if the query string delete is not set ", function() { + this.HttpController.getDoc(this.req, this.res, this.next); + return this.res.send.calledWith(404).should.equal(true); + }); - it "should return the doc as JSON if include_deleted is set to true", -> - @req.query.include_deleted = "true" - @HttpController.getDoc @req, @res, @next - @res.json + return it("should return the doc as JSON if include_deleted is set to true", function() { + this.req.query.include_deleted = "true"; + this.HttpController.getDoc(this.req, this.res, this.next); + return this.res.json .calledWith({ - _id: @doc_id - lines: @doc.lines - rev: @doc.rev - deleted: true - version: @doc.version + _id: this.doc_id, + lines: this.doc.lines, + rev: this.doc.rev, + deleted: true, + version: this.doc.version }) - .should.equal true + .should.equal(true); + }); + }); + }); - describe "getRawDoc", -> - beforeEach -> - @req.params = - project_id: @project_id - doc_id: @doc_id - @DocManager.getDocLines = sinon.stub().callsArgWith(2, null, @doc) - @HttpController.getRawDoc @req, @res, @next + describe("getRawDoc", function() { + beforeEach(function() { + this.req.params = { + project_id: this.project_id, + doc_id: this.doc_id + }; + this.DocManager.getDocLines = sinon.stub().callsArgWith(2, null, this.doc); + return this.HttpController.getRawDoc(this.req, this.res, this.next); + }); - it "should get the document without the version", -> - @DocManager.getDocLines - .calledWith(@project_id, @doc_id) - .should.equal true + it("should get the document without the version", function() { + return this.DocManager.getDocLines + .calledWith(this.project_id, this.doc_id) + .should.equal(true); + }); - it "should set the content type header", -> - @res.setHeader.calledWith('content-type', 'text/plain').should.equal true + it("should set the content type header", function() { + return this.res.setHeader.calledWith('content-type', 'text/plain').should.equal(true); + }); - it "should send the raw version of the doc", -> - assert.deepEqual @res.send.args[0][0], "#{@doc.lines[0]}\n#{@doc.lines[1]}\n#{@doc.lines[2]}\n#{@doc.lines[3]}\n#{@doc.lines[4]}\n#{@doc.lines[5]}" + return it("should send the raw version of the doc", function() { + return assert.deepEqual(this.res.send.args[0][0], `${this.doc.lines[0]}\n${this.doc.lines[1]}\n${this.doc.lines[2]}\n${this.doc.lines[3]}\n${this.doc.lines[4]}\n${this.doc.lines[5]}`); + }); + }); - describe "getAllDocs", -> - describe "normally", -> - beforeEach -> - @req.params = - project_id: @project_id - @docs = [{ - _id: ObjectId() - lines: ["mock", "lines", "one"] + describe("getAllDocs", function() { + describe("normally", function() { + beforeEach(function() { + this.req.params = + {project_id: this.project_id}; + this.docs = [{ + _id: ObjectId(), + lines: ["mock", "lines", "one"], rev: 2 }, { - _id: ObjectId() - lines: ["mock", "lines", "two"] + _id: ObjectId(), + lines: ["mock", "lines", "two"], rev: 4 - }] - @DocManager.getAllNonDeletedDocs = sinon.stub().callsArgWith(2, null, @docs) - @HttpController.getAllDocs @req, @res, @next + }]; + this.DocManager.getAllNonDeletedDocs = sinon.stub().callsArgWith(2, null, this.docs); + return this.HttpController.getAllDocs(this.req, this.res, this.next); + }); - it "should get all the (non-deleted) docs", -> - @DocManager.getAllNonDeletedDocs - .calledWith(@project_id, {lines: true, rev: true}) - .should.equal true + it("should get all the (non-deleted) docs", function() { + return this.DocManager.getAllNonDeletedDocs + .calledWith(this.project_id, {lines: true, rev: true}) + .should.equal(true); + }); - it "should return the doc as JSON", -> - @res.json + return it("should return the doc as JSON", function() { + return this.res.json .calledWith([{ - _id: @docs[0]._id.toString() - lines: @docs[0].lines - rev: @docs[0].rev + _id: this.docs[0]._id.toString(), + lines: this.docs[0].lines, + rev: this.docs[0].rev }, { - _id: @docs[1]._id.toString() - lines: @docs[1].lines - rev: @docs[1].rev + _id: this.docs[1]._id.toString(), + lines: this.docs[1].lines, + rev: this.docs[1].rev }]) - .should.equal true + .should.equal(true); + }); + }); - describe "with a null doc", -> - beforeEach -> - @req.params = - project_id: @project_id - @docs = [{ - _id: ObjectId() - lines: ["mock", "lines", "one"] + return describe("with a null doc", function() { + beforeEach(function() { + this.req.params = + {project_id: this.project_id}; + this.docs = [{ + _id: ObjectId(), + lines: ["mock", "lines", "one"], rev: 2 }, null, { - _id: ObjectId() - lines: ["mock", "lines", "two"] + _id: ObjectId(), + lines: ["mock", "lines", "two"], rev: 4 - }] - @DocManager.getAllNonDeletedDocs = sinon.stub().callsArgWith(2, null, @docs) - @HttpController.getAllDocs @req, @res, @next + }]; + this.DocManager.getAllNonDeletedDocs = sinon.stub().callsArgWith(2, null, this.docs); + return this.HttpController.getAllDocs(this.req, this.res, this.next); + }); - it "should return the non null docs as JSON", -> - @res.json + it("should return the non null docs as JSON", function() { + return this.res.json .calledWith([{ - _id: @docs[0]._id.toString() - lines: @docs[0].lines - rev: @docs[0].rev + _id: this.docs[0]._id.toString(), + lines: this.docs[0].lines, + rev: this.docs[0].rev }, { - _id: @docs[2]._id.toString() - lines: @docs[2].lines - rev: @docs[2].rev + _id: this.docs[2]._id.toString(), + lines: this.docs[2].lines, + rev: this.docs[2].rev }]) - .should.equal true + .should.equal(true); + }); - it "should log out an error", -> - @logger.error - .calledWith( - err: sinon.match.has('message', "null doc") - project_id: @project_id + return it("should log out an error", function() { + return this.logger.error + .calledWith({ + err: sinon.match.has('message', "null doc"), + project_id: this.project_id + }, "encountered null doc" ) - .should.equal true + .should.equal(true); + }); + }); + }); - describe "getAllRanges", -> - describe "normally", -> - beforeEach -> - @req.params = - project_id: @project_id - @docs = [{ - _id: ObjectId() - ranges: {"mock_ranges": "one"} - }, { - _id: ObjectId() - ranges: {"mock_ranges": "two"} - }] - @DocManager.getAllNonDeletedDocs = sinon.stub().callsArgWith(2, null, @docs) - @HttpController.getAllRanges @req, @res, @next + describe("getAllRanges", () => describe("normally", function() { + beforeEach(function() { + this.req.params = + {project_id: this.project_id}; + this.docs = [{ + _id: ObjectId(), + ranges: {"mock_ranges": "one"} + }, { + _id: ObjectId(), + ranges: {"mock_ranges": "two"} + }]; + this.DocManager.getAllNonDeletedDocs = sinon.stub().callsArgWith(2, null, this.docs); + return this.HttpController.getAllRanges(this.req, this.res, this.next); + }); - it "should get all the (non-deleted) doc ranges", -> - @DocManager.getAllNonDeletedDocs - .calledWith(@project_id, {ranges: true}) - .should.equal true + it("should get all the (non-deleted) doc ranges", function() { + return this.DocManager.getAllNonDeletedDocs + .calledWith(this.project_id, {ranges: true}) + .should.equal(true); + }); - it "should return the doc as JSON", -> - @res.json - .calledWith([{ - _id: @docs[0]._id.toString() - ranges: @docs[0].ranges - }, { - _id: @docs[1]._id.toString() - ranges: @docs[1].ranges - }]) - .should.equal true + return it("should return the doc as JSON", function() { + return this.res.json + .calledWith([{ + _id: this.docs[0]._id.toString(), + ranges: this.docs[0].ranges + }, { + _id: this.docs[1]._id.toString(), + ranges: this.docs[1].ranges + }]) + .should.equal(true); + }); + })); - describe "updateDoc", -> - beforeEach -> - @req.params = - project_id: @project_id - doc_id: @doc_id + describe("updateDoc", function() { + beforeEach(function() { + return this.req.params = { + project_id: this.project_id, + doc_id: this.doc_id + }; + }); - describe "when the doc lines exist and were updated", -> - beforeEach -> - @req.body = - lines: @lines = ["hello", "world"] - version: @version = 42 - ranges: @ranges = { changes: "mock" } - @DocManager.updateDoc = sinon.stub().yields(null, true, @rev = 5) - @HttpController.updateDoc @req, @res, @next + describe("when the doc lines exist and were updated", function() { + beforeEach(function() { + this.req.body = { + lines: (this.lines = ["hello", "world"]), + version: (this.version = 42), + ranges: (this.ranges = { changes: "mock" }) + }; + this.DocManager.updateDoc = sinon.stub().yields(null, true, (this.rev = 5)); + return this.HttpController.updateDoc(this.req, this.res, this.next); + }); - it "should update the document", -> - @DocManager.updateDoc - .calledWith(@project_id, @doc_id, @lines, @version, @ranges) - .should.equal true + it("should update the document", function() { + return this.DocManager.updateDoc + .calledWith(this.project_id, this.doc_id, this.lines, this.version, this.ranges) + .should.equal(true); + }); - it "should return a modified status", -> - @res.json - .calledWith(modified: true, rev: @rev) - .should.equal true + return it("should return a modified status", function() { + return this.res.json + .calledWith({modified: true, rev: this.rev}) + .should.equal(true); + }); + }); - describe "when the doc lines exist and were not updated", -> - beforeEach -> - @req.body = - lines: @lines = ["hello", "world"] - version: @version = 42 + describe("when the doc lines exist and were not updated", function() { + beforeEach(function() { + this.req.body = { + lines: (this.lines = ["hello", "world"]), + version: (this.version = 42), ranges: {} - @DocManager.updateDoc = sinon.stub().yields(null, false, @rev = 5) - @HttpController.updateDoc @req, @res, @next + }; + this.DocManager.updateDoc = sinon.stub().yields(null, false, (this.rev = 5)); + return this.HttpController.updateDoc(this.req, this.res, this.next); + }); - it "should return a modified status", -> - @res.json - .calledWith(modified: false, rev: @rev) - .should.equal true + return it("should return a modified status", function() { + return this.res.json + .calledWith({modified: false, rev: this.rev}) + .should.equal(true); + }); + }); - describe "when the doc lines are not provided", -> - beforeEach -> - @req.body = { version: 42, ranges: {} } - @DocManager.updateDoc = sinon.stub().yields(null, false) - @HttpController.updateDoc @req, @res, @next + describe("when the doc lines are not provided", function() { + beforeEach(function() { + this.req.body = { version: 42, ranges: {} }; + this.DocManager.updateDoc = sinon.stub().yields(null, false); + return this.HttpController.updateDoc(this.req, this.res, this.next); + }); - it "should not update the document", -> - @DocManager.updateDoc.called.should.equal false + it("should not update the document", function() { + return this.DocManager.updateDoc.called.should.equal(false); + }); - it "should return a 400 (bad request) response", -> - @res.send + return it("should return a 400 (bad request) response", function() { + return this.res.send .calledWith(400) - .should.equal true + .should.equal(true); + }); + }); - describe "when the doc version are not provided", -> - beforeEach -> - @req.body = { version: 42, lines: ["hello world"] } - @DocManager.updateDoc = sinon.stub().yields(null, false) - @HttpController.updateDoc @req, @res, @next + describe("when the doc version are not provided", function() { + beforeEach(function() { + this.req.body = { version: 42, lines: ["hello world"] }; + this.DocManager.updateDoc = sinon.stub().yields(null, false); + return this.HttpController.updateDoc(this.req, this.res, this.next); + }); - it "should not update the document", -> - @DocManager.updateDoc.called.should.equal false + it("should not update the document", function() { + return this.DocManager.updateDoc.called.should.equal(false); + }); - it "should return a 400 (bad request) response", -> - @res.send + return it("should return a 400 (bad request) response", function() { + return this.res.send .calledWith(400) - .should.equal true + .should.equal(true); + }); + }); - describe "when the doc ranges is not provided", -> - beforeEach -> - @req.body = { lines : [ "foo" ], version: 42 } - @DocManager.updateDoc = sinon.stub().yields(null, false) - @HttpController.updateDoc @req, @res, @next + describe("when the doc ranges is not provided", function() { + beforeEach(function() { + this.req.body = { lines : [ "foo" ], version: 42 }; + this.DocManager.updateDoc = sinon.stub().yields(null, false); + return this.HttpController.updateDoc(this.req, this.res, this.next); + }); - it "should not update the document", -> - @DocManager.updateDoc.called.should.equal false + it("should not update the document", function() { + return this.DocManager.updateDoc.called.should.equal(false); + }); - it "should return a 400 (bad request) response", -> - @res.send + return it("should return a 400 (bad request) response", function() { + return this.res.send .calledWith(400) - .should.equal true + .should.equal(true); + }); + }); - describe "when the doc body is too large", -> - beforeEach -> - @req.body = - lines: @lines = Array(2049).fill('a'.repeat(1024)) - version: @version = 42 - ranges: @ranges = { changes: "mock" } - @HttpController.updateDoc @req, @res, @next + return describe("when the doc body is too large", function() { + beforeEach(function() { + this.req.body = { + lines: (this.lines = Array(2049).fill('a'.repeat(1024))), + version: (this.version = 42), + ranges: (this.ranges = { changes: "mock" }) + }; + return this.HttpController.updateDoc(this.req, this.res, this.next); + }); - it "should return a 413 (too large) response", -> - sinon.assert.calledWith(@res.status, 413) + it("should return a 413 (too large) response", function() { + return sinon.assert.calledWith(this.res.status, 413); + }); - it "should report that the document body is too large", -> - sinon.assert.calledWith(@res.send, "document body too large") + return it("should report that the document body is too large", function() { + return sinon.assert.calledWith(this.res.send, "document body too large"); + }); + }); + }); - describe "deleteDoc", -> - beforeEach -> - @req.params = - project_id: @project_id - doc_id: @doc_id - @DocManager.deleteDoc = sinon.stub().callsArg(2) - @HttpController.deleteDoc @req, @res, @next + describe("deleteDoc", function() { + beforeEach(function() { + this.req.params = { + project_id: this.project_id, + doc_id: this.doc_id + }; + this.DocManager.deleteDoc = sinon.stub().callsArg(2); + return this.HttpController.deleteDoc(this.req, this.res, this.next); + }); - it "should delete the document", -> - @DocManager.deleteDoc - .calledWith(@project_id, @doc_id) - .should.equal true + it("should delete the document", function() { + return this.DocManager.deleteDoc + .calledWith(this.project_id, this.doc_id) + .should.equal(true); + }); - it "should return a 204 (No Content)", -> - @res.send + return it("should return a 204 (No Content)", function() { + return this.res.send .calledWith(204) - .should.equal true + .should.equal(true); + }); + }); - describe "archiveAllDocs", -> - beforeEach -> - @req.params = - project_id: @project_id - @DocArchiveManager.archiveAllDocs = sinon.stub().callsArg(1) - @HttpController.archiveAllDocs @req, @res, @next + describe("archiveAllDocs", function() { + beforeEach(function() { + this.req.params = + {project_id: this.project_id}; + this.DocArchiveManager.archiveAllDocs = sinon.stub().callsArg(1); + return this.HttpController.archiveAllDocs(this.req, this.res, this.next); + }); - it "should archive the project", -> - @DocArchiveManager.archiveAllDocs - .calledWith(@project_id) - .should.equal true + it("should archive the project", function() { + return this.DocArchiveManager.archiveAllDocs + .calledWith(this.project_id) + .should.equal(true); + }); - it "should return a 204 (No Content)", -> - @res.send + return it("should return a 204 (No Content)", function() { + return this.res.send .calledWith(204) - .should.equal true + .should.equal(true); + }); + }); - describe "destroyAllDocs", -> - beforeEach -> - @req.params = - project_id: @project_id - @DocArchiveManager.destroyAllDocs = sinon.stub().callsArg(1) - @HttpController.destroyAllDocs @req, @res, @next + return describe("destroyAllDocs", function() { + beforeEach(function() { + this.req.params = + {project_id: this.project_id}; + this.DocArchiveManager.destroyAllDocs = sinon.stub().callsArg(1); + return this.HttpController.destroyAllDocs(this.req, this.res, this.next); + }); - it "should destroy the docs", -> - sinon.assert.calledWith(@DocArchiveManager.destroyAllDocs, @project_id) + it("should destroy the docs", function() { + return sinon.assert.calledWith(this.DocArchiveManager.destroyAllDocs, this.project_id); + }); - it "should return 204", -> - sinon.assert.calledWith(@res.send, 204) + return it("should return 204", function() { + return sinon.assert.calledWith(this.res.send, 204); + }); + }); +}); diff --git a/services/docstore/test/unit/coffee/MongoManagerTests.js b/services/docstore/test/unit/coffee/MongoManagerTests.js index 842a3c8884..0832c89d21 100644 --- a/services/docstore/test/unit/coffee/MongoManagerTests.js +++ b/services/docstore/test/unit/coffee/MongoManagerTests.js @@ -1,168 +1,225 @@ -SandboxedModule = require('sandboxed-module') -sinon = require('sinon') -require('chai').should() -modulePath = require('path').join __dirname, '../../../app/js/MongoManager' -ObjectId = require("mongojs").ObjectId -assert = require("chai").assert +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +const SandboxedModule = require('sandboxed-module'); +const sinon = require('sinon'); +require('chai').should(); +const modulePath = require('path').join(__dirname, '../../../app/js/MongoManager'); +const { + ObjectId +} = require("mongojs"); +const { + assert +} = require("chai"); -describe "MongoManager", -> - beforeEach -> - @MongoManager = SandboxedModule.require modulePath, requires: - "./mongojs": - db: @db = { docs: {}, docOps: {} } - ObjectId: ObjectId - 'metrics-sharelatex': {timeAsyncMethod: sinon.stub()} - 'logger-sharelatex': {log: ()->} - @project_id = ObjectId().toString() - @doc_id = ObjectId().toString() - @callback = sinon.stub() - @stubbedErr = new Error("hello world") +describe("MongoManager", function() { + beforeEach(function() { + this.MongoManager = SandboxedModule.require(modulePath, { requires: { + "./mongojs": { + db: (this.db = { docs: {}, docOps: {} }), + ObjectId + }, + 'metrics-sharelatex': {timeAsyncMethod: sinon.stub()}, + 'logger-sharelatex': {log(){}} + } + }); + this.project_id = ObjectId().toString(); + this.doc_id = ObjectId().toString(); + this.callback = sinon.stub(); + return this.stubbedErr = new Error("hello world"); + }); - describe "findDoc", -> - beforeEach -> - @doc = { name: "mock-doc"} - @db.docs.find = sinon.stub().callsArgWith(2, null, [@doc]) - @filter = { lines: true } - @MongoManager.findDoc @project_id, @doc_id, @filter, @callback + describe("findDoc", function() { + beforeEach(function() { + this.doc = { name: "mock-doc"}; + this.db.docs.find = sinon.stub().callsArgWith(2, null, [this.doc]); + this.filter = { lines: true }; + return this.MongoManager.findDoc(this.project_id, this.doc_id, this.filter, this.callback); + }); - it "should find the doc", -> - @db.docs.find + it("should find the doc", function() { + return this.db.docs.find .calledWith({ - _id: ObjectId(@doc_id) - project_id: ObjectId(@project_id) - }, @filter) - .should.equal true + _id: ObjectId(this.doc_id), + project_id: ObjectId(this.project_id) + }, this.filter) + .should.equal(true); + }); - it "should call the callback with the doc", -> - @callback.calledWith(null, @doc).should.equal true + return it("should call the callback with the doc", function() { + return this.callback.calledWith(null, this.doc).should.equal(true); + }); + }); - describe "getProjectsDocs", -> - beforeEach -> - @filter = {lines: true} - @doc1 = { name: "mock-doc1" } - @doc2 = { name: "mock-doc2" } - @doc3 = { name: "mock-doc3" } - @doc4 = { name: "mock-doc4" } - @db.docs.find = sinon.stub().callsArgWith(2, null, [@doc, @doc3, @doc4]) + describe("getProjectsDocs", function() { + beforeEach(function() { + this.filter = {lines: true}; + this.doc1 = { name: "mock-doc1" }; + this.doc2 = { name: "mock-doc2" }; + this.doc3 = { name: "mock-doc3" }; + this.doc4 = { name: "mock-doc4" }; + return this.db.docs.find = sinon.stub().callsArgWith(2, null, [this.doc, this.doc3, this.doc4]); + }); - describe "with included_deleted = false", -> - beforeEach -> - @MongoManager.getProjectsDocs @project_id, include_deleted: false, @filter, @callback + describe("with included_deleted = false", function() { + beforeEach(function() { + return this.MongoManager.getProjectsDocs(this.project_id, {include_deleted: false}, this.filter, this.callback); + }); - it "should find the non-deleted docs via the project_id", -> - @db.docs.find + it("should find the non-deleted docs via the project_id", function() { + return this.db.docs.find .calledWith({ - project_id: ObjectId(@project_id) + project_id: ObjectId(this.project_id), deleted: { $ne: true } - }, @filter) - .should.equal true + }, this.filter) + .should.equal(true); + }); - it "should call the callback with the docs", -> - @callback.calledWith(null, [@doc, @doc3, @doc4]).should.equal true + return it("should call the callback with the docs", function() { + return this.callback.calledWith(null, [this.doc, this.doc3, this.doc4]).should.equal(true); + }); + }); - describe "with included_deleted = true", -> - beforeEach -> - @MongoManager.getProjectsDocs @project_id, include_deleted: true, @filter, @callback + return describe("with included_deleted = true", function() { + beforeEach(function() { + return this.MongoManager.getProjectsDocs(this.project_id, {include_deleted: true}, this.filter, this.callback); + }); - it "should find all via the project_id", -> - @db.docs.find + it("should find all via the project_id", function() { + return this.db.docs.find .calledWith({ - project_id: ObjectId(@project_id) - }, @filter) - .should.equal true + project_id: ObjectId(this.project_id) + }, this.filter) + .should.equal(true); + }); - it "should call the callback with the docs", -> - @callback.calledWith(null, [@doc, @doc3, @doc4]).should.equal true + return it("should call the callback with the docs", function() { + return this.callback.calledWith(null, [this.doc, this.doc3, this.doc4]).should.equal(true); + }); + }); + }); - describe "upsertIntoDocCollection", -> - beforeEach -> - @db.docs.update = sinon.stub().callsArgWith(3, @stubbedErr) - @oldRev = 77 + describe("upsertIntoDocCollection", function() { + beforeEach(function() { + this.db.docs.update = sinon.stub().callsArgWith(3, this.stubbedErr); + return this.oldRev = 77; + }); - it "should upsert the document", (done)-> - @MongoManager.upsertIntoDocCollection @project_id, @doc_id, {@lines}, (err)=> - args = @db.docs.update.args[0] - assert.deepEqual args[0], {_id: ObjectId(@doc_id)} - assert.equal args[1]["$set"]["lines"], @lines - assert.equal args[1]["$inc"]["rev"], 1 - assert.deepEqual args[1]["$set"]["project_id"], ObjectId(@project_id) - done() + it("should upsert the document", function(done){ + return this.MongoManager.upsertIntoDocCollection(this.project_id, this.doc_id, {lines: this.lines}, err=> { + const args = this.db.docs.update.args[0]; + assert.deepEqual(args[0], {_id: ObjectId(this.doc_id)}); + assert.equal(args[1]["$set"]["lines"], this.lines); + assert.equal(args[1]["$inc"]["rev"], 1); + assert.deepEqual(args[1]["$set"]["project_id"], ObjectId(this.project_id)); + return done(); + }); + }); - it "should return the error", (done)-> - @MongoManager.upsertIntoDocCollection @project_id, @doc_id, {@lines}, (err)=> - err.should.equal @stubbedErr - done() + return it("should return the error", function(done){ + return this.MongoManager.upsertIntoDocCollection(this.project_id, this.doc_id, {lines: this.lines}, err=> { + err.should.equal(this.stubbedErr); + return done(); + }); + }); + }); - describe "markDocAsDeleted", -> - beforeEach -> - @db.docs.update = sinon.stub().callsArgWith(2, @stubbedErr) - @oldRev = 77 + describe("markDocAsDeleted", function() { + beforeEach(function() { + this.db.docs.update = sinon.stub().callsArgWith(2, this.stubbedErr); + return this.oldRev = 77; + }); - it "should process the update", (done) -> - @MongoManager.markDocAsDeleted @project_id, @doc_id, (err)=> - args = @db.docs.update.args[0] - assert.deepEqual args[0], {_id: ObjectId(@doc_id), project_id: ObjectId(@project_id)} - assert.equal args[1]["$set"]["deleted"], true - done() + it("should process the update", function(done) { + return this.MongoManager.markDocAsDeleted(this.project_id, this.doc_id, err=> { + const args = this.db.docs.update.args[0]; + assert.deepEqual(args[0], {_id: ObjectId(this.doc_id), project_id: ObjectId(this.project_id)}); + assert.equal(args[1]["$set"]["deleted"], true); + return done(); + }); + }); - it "should return the error", (done)-> - @MongoManager.markDocAsDeleted @project_id, @doc_id, (err)=> - err.should.equal @stubbedErr - done() + return it("should return the error", function(done){ + return this.MongoManager.markDocAsDeleted(this.project_id, this.doc_id, err=> { + err.should.equal(this.stubbedErr); + return done(); + }); + }); + }); - describe "destroyDoc", -> - beforeEach (done) -> - @db.docs.remove = sinon.stub().yields() - @db.docOps.remove = sinon.stub().yields() - @MongoManager.destroyDoc '123456789012', done + describe("destroyDoc", function() { + beforeEach(function(done) { + this.db.docs.remove = sinon.stub().yields(); + this.db.docOps.remove = sinon.stub().yields(); + return this.MongoManager.destroyDoc('123456789012', done); + }); - it "should destroy the doc", -> - sinon.assert.calledWith(@db.docs.remove, {_id: ObjectId('123456789012')}) + it("should destroy the doc", function() { + return sinon.assert.calledWith(this.db.docs.remove, {_id: ObjectId('123456789012')}); + }); - it "should destroy the docOps", -> - sinon.assert.calledWith(@db.docOps.remove, {doc_id: ObjectId('123456789012')}) + return it("should destroy the docOps", function() { + return sinon.assert.calledWith(this.db.docOps.remove, {doc_id: ObjectId('123456789012')}); + }); + }); - describe "getDocVersion", -> - describe "when the doc exists", -> - beforeEach -> - @doc = - version: @version = 42 - @db.docOps.find = sinon.stub().callsArgWith(2, null, [@doc]) - @MongoManager.getDocVersion @doc_id, @callback + describe("getDocVersion", function() { + describe("when the doc exists", function() { + beforeEach(function() { + this.doc = + {version: (this.version = 42)}; + this.db.docOps.find = sinon.stub().callsArgWith(2, null, [this.doc]); + return this.MongoManager.getDocVersion(this.doc_id, this.callback); + }); - it "should look for the doc in the database", -> - @db.docOps.find - .calledWith({ doc_id: ObjectId(@doc_id) }, {version: 1}) - .should.equal true + it("should look for the doc in the database", function() { + return this.db.docOps.find + .calledWith({ doc_id: ObjectId(this.doc_id) }, {version: 1}) + .should.equal(true); + }); - it "should call the callback with the version", -> - @callback.calledWith(null, @version).should.equal true + return it("should call the callback with the version", function() { + return this.callback.calledWith(null, this.version).should.equal(true); + }); + }); - describe "when the doc doesn't exist", -> - beforeEach -> - @db.docOps.find = sinon.stub().callsArgWith(2, null, []) - @MongoManager.getDocVersion @doc_id, @callback + return describe("when the doc doesn't exist", function() { + beforeEach(function() { + this.db.docOps.find = sinon.stub().callsArgWith(2, null, []); + return this.MongoManager.getDocVersion(this.doc_id, this.callback); + }); - it "should call the callback with 0", -> - @callback.calledWith(null, 0).should.equal true + return it("should call the callback with 0", function() { + return this.callback.calledWith(null, 0).should.equal(true); + }); + }); + }); - describe "setDocVersion", -> - beforeEach -> - @version = 42 - @db.docOps.update = sinon.stub().callsArg(3) - @MongoManager.setDocVersion @doc_id, @version, @callback + return describe("setDocVersion", function() { + beforeEach(function() { + this.version = 42; + this.db.docOps.update = sinon.stub().callsArg(3); + return this.MongoManager.setDocVersion(this.doc_id, this.version, this.callback); + }); - it "should update the doc version", -> - @db.docOps.update + it("should update the doc version", function() { + return this.db.docOps.update .calledWith({ - doc_id: ObjectId(@doc_id) + doc_id: ObjectId(this.doc_id) }, { - $set: - version: @version + $set: { + version: this.version + } }, { upsert: true }) - .should.equal true + .should.equal(true); + }); - it "should call the callback", -> - @callback.called.should.equal true + return it("should call the callback", function() { + return this.callback.called.should.equal(true); + }); + }); +}); diff --git a/services/docstore/test/unit/coffee/RangeManagerTests.js b/services/docstore/test/unit/coffee/RangeManagerTests.js index ea2416ab63..f98ca2cbe9 100644 --- a/services/docstore/test/unit/coffee/RangeManagerTests.js +++ b/services/docstore/test/unit/coffee/RangeManagerTests.js @@ -1,155 +1,192 @@ -SandboxedModule = require('sandboxed-module') -sinon = require('sinon') -require('chai').should() -expect = require('chai').expect -modulePath = require('path').join __dirname, '../../../app/js/RangeManager' -ObjectId = require("mongojs").ObjectId -assert = require("chai").assert -_ = require "underscore" +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +const SandboxedModule = require('sandboxed-module'); +const sinon = require('sinon'); +require('chai').should(); +const { + expect +} = require('chai'); +const modulePath = require('path').join(__dirname, '../../../app/js/RangeManager'); +const { + ObjectId +} = require("mongojs"); +const { + assert +} = require("chai"); +const _ = require("underscore"); -describe "RangeManager", -> - beforeEach -> - @RangeManager = SandboxedModule.require modulePath, requires: - "./mongojs": - ObjectId: ObjectId +describe("RangeManager", function() { + beforeEach(function() { + return this.RangeManager = SandboxedModule.require(modulePath, { requires: { + "./mongojs": { + ObjectId + } + } + } + ); + }); - describe "jsonRangesToMongo", -> - it "should convert ObjectIds and dates to proper objects", -> - change_id = ObjectId().toString() - comment_id = ObjectId().toString() - user_id = ObjectId().toString() - thread_id = ObjectId().toString() - ts = new Date().toJSON() - @RangeManager.jsonRangesToMongo({ + describe("jsonRangesToMongo", function() { + it("should convert ObjectIds and dates to proper objects", function() { + const change_id = ObjectId().toString(); + const comment_id = ObjectId().toString(); + const user_id = ObjectId().toString(); + const thread_id = ObjectId().toString(); + const ts = new Date().toJSON(); + return this.RangeManager.jsonRangesToMongo({ changes: [{ - id: change_id - op: { i: "foo", p: 3 } - metadata: - user_id: user_id - ts: ts - }] + id: change_id, + op: { i: "foo", p: 3 }, + metadata: { + user_id, + ts + } + }], comments: [{ - id: comment_id + id: comment_id, op: { c: "foo", p: 3, t: thread_id } }] - }).should.deep.equal { + }).should.deep.equal({ changes: [{ - id: ObjectId(change_id) - op: { i: "foo", p: 3 } - metadata: - user_id: ObjectId(user_id) + id: ObjectId(change_id), + op: { i: "foo", p: 3 }, + metadata: { + user_id: ObjectId(user_id), ts: new Date(ts) - }] + } + }], comments: [{ - id: ObjectId(comment_id) + id: ObjectId(comment_id), op: { c: "foo", p: 3, t: ObjectId(thread_id) } }] - } + }); + }); - it "should leave malformed ObjectIds as they are", -> - change_id = "foo" - comment_id = "bar" - user_id = "baz" - @RangeManager.jsonRangesToMongo({ + it("should leave malformed ObjectIds as they are", function() { + const change_id = "foo"; + const comment_id = "bar"; + const user_id = "baz"; + return this.RangeManager.jsonRangesToMongo({ changes: [{ - id: change_id - metadata: - user_id: user_id - }] + id: change_id, + metadata: { + user_id + } + }], comments: [{ id: comment_id }] - }).should.deep.equal { + }).should.deep.equal({ changes: [{ - id: change_id - metadata: - user_id: user_id - }] + id: change_id, + metadata: { + user_id + } + }], comments: [{ id: comment_id }] - } + }); + }); - it "should be consistent when transformed through json -> mongo -> json", -> - change_id = ObjectId().toString() - comment_id = ObjectId().toString() - user_id = ObjectId().toString() - thread_id = ObjectId().toString() - ts = new Date().toJSON() - ranges1 = { + return it("should be consistent when transformed through json -> mongo -> json", function() { + const change_id = ObjectId().toString(); + const comment_id = ObjectId().toString(); + const user_id = ObjectId().toString(); + const thread_id = ObjectId().toString(); + const ts = new Date().toJSON(); + const ranges1 = { changes: [{ - id: change_id - op: { i: "foo", p: 3 } - metadata: - user_id: user_id - ts: ts - }] + id: change_id, + op: { i: "foo", p: 3 }, + metadata: { + user_id, + ts + } + }], comments: [{ - id: comment_id + id: comment_id, op: { c: "foo", p: 3, t: thread_id } }] - } - ranges1_copy = JSON.parse(JSON.stringify(ranges1)) # jsonRangesToMongo modifies in place - ranges2 = JSON.parse(JSON.stringify(@RangeManager.jsonRangesToMongo(ranges1_copy))) - ranges1.should.deep.equal ranges2 + }; + const ranges1_copy = JSON.parse(JSON.stringify(ranges1)); // jsonRangesToMongo modifies in place + const ranges2 = JSON.parse(JSON.stringify(this.RangeManager.jsonRangesToMongo(ranges1_copy))); + return ranges1.should.deep.equal(ranges2); + }); + }); - describe "shouldUpdateRanges", -> - beforeEach () -> - @ranges = { + return describe("shouldUpdateRanges", function() { + beforeEach(function() { + this.ranges = { changes: [{ - id: ObjectId() - op: { i: "foo", p: 3 } - metadata: - user_id: ObjectId() + id: ObjectId(), + op: { i: "foo", p: 3 }, + metadata: { + user_id: ObjectId(), ts: new Date() - }] + } + }], comments: [{ - id: ObjectId() + id: ObjectId(), op: { c: "foo", p: 3, t: ObjectId() } }] - } - @ranges_copy = @RangeManager.jsonRangesToMongo(JSON.parse(JSON.stringify(@ranges))) + }; + return this.ranges_copy = this.RangeManager.jsonRangesToMongo(JSON.parse(JSON.stringify(this.ranges))); + }); - describe "with a blank new range", -> - it "should throw an error", -> - expect(() => - @RangeManager.shouldUpdateRanges(@ranges, null) - ).to.throw(Error) + describe("with a blank new range", () => it("should throw an error", function() { + return expect(() => { + return this.RangeManager.shouldUpdateRanges(this.ranges, null); + }).to.throw(Error); + })); - describe "with a blank old range", -> - it "should treat it like {}", -> - @RangeManager.shouldUpdateRanges(null, {}).should.equal false - @RangeManager.shouldUpdateRanges(null, @ranges).should.equal true + describe("with a blank old range", () => it("should treat it like {}", function() { + this.RangeManager.shouldUpdateRanges(null, {}).should.equal(false); + return this.RangeManager.shouldUpdateRanges(null, this.ranges).should.equal(true); + })); - describe "with no changes", -> - it "should return false", -> - @RangeManager.shouldUpdateRanges(@ranges, @ranges_copy).should.equal false + describe("with no changes", () => it("should return false", function() { + return this.RangeManager.shouldUpdateRanges(this.ranges, this.ranges_copy).should.equal(false); + })); - describe "with changes", -> - it "should return true when the change id changes", -> - @ranges_copy.changes[0].id = ObjectId() - @RangeManager.shouldUpdateRanges(@ranges, @ranges_copy).should.equal true + return describe("with changes", function() { + it("should return true when the change id changes", function() { + this.ranges_copy.changes[0].id = ObjectId(); + return this.RangeManager.shouldUpdateRanges(this.ranges, this.ranges_copy).should.equal(true); + }); - it "should return true when the change user id changes", -> - @ranges_copy.changes[0].metadata.user_id = ObjectId() - @RangeManager.shouldUpdateRanges(@ranges, @ranges_copy).should.equal true + it("should return true when the change user id changes", function() { + this.ranges_copy.changes[0].metadata.user_id = ObjectId(); + return this.RangeManager.shouldUpdateRanges(this.ranges, this.ranges_copy).should.equal(true); + }); - it "should return true when the change ts changes", -> - @ranges_copy.changes[0].metadata.ts = new Date(Date.now() + 1000) - @RangeManager.shouldUpdateRanges(@ranges, @ranges_copy).should.equal true + it("should return true when the change ts changes", function() { + this.ranges_copy.changes[0].metadata.ts = new Date(Date.now() + 1000); + return this.RangeManager.shouldUpdateRanges(this.ranges, this.ranges_copy).should.equal(true); + }); - it "should return true when the change op changes", -> - @ranges_copy.changes[0].op.i = "bar" - @RangeManager.shouldUpdateRanges(@ranges, @ranges_copy).should.equal true + it("should return true when the change op changes", function() { + this.ranges_copy.changes[0].op.i = "bar"; + return this.RangeManager.shouldUpdateRanges(this.ranges, this.ranges_copy).should.equal(true); + }); - it "should return true when the comment id changes", -> - @ranges_copy.comments[0].id = ObjectId() - @RangeManager.shouldUpdateRanges(@ranges, @ranges_copy).should.equal true + it("should return true when the comment id changes", function() { + this.ranges_copy.comments[0].id = ObjectId(); + return this.RangeManager.shouldUpdateRanges(this.ranges, this.ranges_copy).should.equal(true); + }); - it "should return true when the comment offset changes", -> - @ranges_copy.comments[0].op.p = 17 - @RangeManager.shouldUpdateRanges(@ranges, @ranges_copy).should.equal true + it("should return true when the comment offset changes", function() { + this.ranges_copy.comments[0].op.p = 17; + return this.RangeManager.shouldUpdateRanges(this.ranges, this.ranges_copy).should.equal(true); + }); - it "should return true when the comment content changes", -> - @ranges_copy.comments[0].op.c = "bar" - @RangeManager.shouldUpdateRanges(@ranges, @ranges_copy).should.equal true \ No newline at end of file + return it("should return true when the comment content changes", function() { + this.ranges_copy.comments[0].op.c = "bar"; + return this.RangeManager.shouldUpdateRanges(this.ranges, this.ranges_copy).should.equal(true); + }); + }); + }); +}); \ No newline at end of file From 6e498152fdac29c2f5d31d3e3d7ecb43713ca5e3 Mon Sep 17 00:00:00 2001 From: decaffeinate Date: Sun, 16 Feb 2020 14:02:49 +0000 Subject: [PATCH 11/27] decaffeinate: Run post-processing cleanups on DocArchiveManagerTests.coffee and 4 other files --- .../unit/coffee/DocArchiveManagerTests.js | 44 +++++++++++-------- .../test/unit/coffee/DocManagerTests.js | 13 +++++- .../test/unit/coffee/HttpControllerTests.js | 10 ++++- .../test/unit/coffee/MongoManagerTests.js | 14 ++++-- .../test/unit/coffee/RangeManagerTests.js | 19 +++++--- 5 files changed, 68 insertions(+), 32 deletions(-) diff --git a/services/docstore/test/unit/coffee/DocArchiveManagerTests.js b/services/docstore/test/unit/coffee/DocArchiveManagerTests.js index a6602405bd..97cfa73140 100644 --- a/services/docstore/test/unit/coffee/DocArchiveManagerTests.js +++ b/services/docstore/test/unit/coffee/DocArchiveManagerTests.js @@ -1,3 +1,11 @@ +/* eslint-disable + camelcase, + handle-callback-err, + no-return-assign, + no-unused-vars, +*/ +// TODO: This file was created by bulk-decaffeinate. +// Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS101: Remove unnecessary use of Array.from @@ -261,7 +269,7 @@ describe("DocArchiveManager", function() { this.MongoManager.getArchivedProjectDocs = sinon.stub().callsArgWith(1, null, this.archivedDocs); this.DocArchiveManager.unarchiveDoc = sinon.stub().callsArgWith(2, null); return this.DocArchiveManager.unArchiveAllDocs(this.project_id, err=> { - for (let doc of Array.from(this.archivedDocs)) { + for (const doc of Array.from(this.archivedDocs)) { this.DocArchiveManager.unarchiveDoc.calledWith(this.project_id, doc._id).should.equal(true); } should.not.exist(err); @@ -299,7 +307,7 @@ describe("DocArchiveManager", function() { it("should destroy all the docs", function(done){ this.DocArchiveManager.destroyDoc = sinon.stub().callsArgWith(2, null); return this.DocArchiveManager.destroyAllDocs(this.project_id, err=> { - for (let doc of Array.from(this.mixedDocs)) { + for (const doc of Array.from(this.mixedDocs)) { this.DocArchiveManager.destroyDoc.calledWith(this.project_id, doc._id).should.equal(true); } should.not.exist(err); @@ -337,7 +345,7 @@ describe("DocArchiveManager", function() { return expect(err).not.to.exist; }); - for (let doc of Array.from(this.mixedDocs)) { + for (const doc of Array.from(this.mixedDocs)) { sinon.assert.calledWith(this.MongoManager.destroyDoc, doc._id); } @@ -346,14 +354,14 @@ describe("DocArchiveManager", function() { }); describe("_s3DocToMongoDoc", function() { - describe("with the old schema", () => it("should return the docs lines", function(done) { - return this.DocArchiveManager._s3DocToMongoDoc(["doc", "lines"], function(error, doc) { + describe("with the old schema", function() { return it("should return the docs lines", function(done) { + return this.DocArchiveManager._s3DocToMongoDoc(["doc", "lines"], (error, doc) => { expect(doc).to.deep.equal({ lines: ["doc", "lines"] }); return done(); }); - })); + }); }); describe("with the new schema", function() { it("should return the doc lines and ranges", function(done) { @@ -362,7 +370,7 @@ describe("DocArchiveManager", function() { lines: ["doc", "lines"], ranges: {"json": "ranges"}, schema_v: 1 - }, function(error, doc) { + }, (error, doc) => { expect(doc).to.deep.equal({ lines: ["doc", "lines"], ranges: {"mongo": "ranges"} @@ -375,7 +383,7 @@ describe("DocArchiveManager", function() { return this.DocArchiveManager._s3DocToMongoDoc({ lines: ["doc", "lines"], schema_v: 1 - }, function(error, doc) { + }, (error, doc) => { expect(doc).to.deep.equal({ lines: ["doc", "lines"] }); @@ -384,23 +392,23 @@ describe("DocArchiveManager", function() { }); }); - return describe("with an unrecognised schema", () => it("should return an error", function(done) { + return describe("with an unrecognised schema", function() { return it("should return an error", function(done) { return this.DocArchiveManager._s3DocToMongoDoc({ schema_v: 2 - }, function(error, doc) { + }, (error, doc) => { expect(error).to.exist; return done(); }); - })); + }); }); }); return describe("_mongoDocToS3Doc", function() { - describe("with a valid doc", () => it("should return the json version", function(done) { + describe("with a valid doc", function() { return it("should return the json version", function(done) { let doc; return this.DocArchiveManager._mongoDocToS3Doc((doc = { lines: ["doc", "lines"], ranges: { "mock": "ranges" } - }), function(err, s3_doc) { + }), (err, s3_doc) => { expect(s3_doc).to.equal(JSON.stringify({ lines: ["doc", "lines"], ranges: { "mock": "ranges" }, @@ -409,7 +417,7 @@ describe("DocArchiveManager", function() { ); return done(); }); - })); + }); }); describe("with null bytes in the result", function() { beforeEach(function() { @@ -425,19 +433,19 @@ describe("DocArchiveManager", function() { return this.DocArchiveManager._mongoDocToS3Doc({ lines: ["doc", "lines"], ranges: { "mock": "ranges" } - }, function(err, s3_doc) { + }, (err, s3_doc) => { expect(err).to.exist; return done(); }); }); }); - return describe("without doc lines", () => it("should return an error", function(done) { - return this.DocArchiveManager._mongoDocToS3Doc({}, function(err, s3_doc) { + return describe("without doc lines", function() { return it("should return an error", function(done) { + return this.DocArchiveManager._mongoDocToS3Doc({}, (err, s3_doc) => { expect(err).to.exist; return done(); }); - })); + }); }); }); }); diff --git a/services/docstore/test/unit/coffee/DocManagerTests.js b/services/docstore/test/unit/coffee/DocManagerTests.js index bdeb97c98d..4130818601 100644 --- a/services/docstore/test/unit/coffee/DocManagerTests.js +++ b/services/docstore/test/unit/coffee/DocManagerTests.js @@ -1,3 +1,12 @@ +/* eslint-disable + camelcase, + handle-callback-err, + no-dupe-keys, + no-return-assign, + no-unused-vars, +*/ +// TODO: This file was created by bulk-decaffeinate. +// Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS102: Remove unnecessary code created because of implicit returns @@ -143,7 +152,7 @@ describe("DocManager", function() { }); it("should error if inS3 is not set to true", function(done){ - return this.DocManager._getDoc(this.project_id, this.doc_id, {inS3: false}, function(err){ + return this.DocManager._getDoc(this.project_id, this.doc_id, {inS3: false}, (err) => { expect(err).to.exist; return done(); }); @@ -158,7 +167,7 @@ describe("DocManager", function() { }); return it("should not error if inS3 is set to true", function(done){ - return this.DocManager._getDoc(this.project_id, this.doc_id, {inS3: true}, function(err){ + return this.DocManager._getDoc(this.project_id, this.doc_id, {inS3: true}, (err) => { expect(err).to.not.exist; return done(); }); diff --git a/services/docstore/test/unit/coffee/HttpControllerTests.js b/services/docstore/test/unit/coffee/HttpControllerTests.js index 615ed5c798..27bb31a325 100644 --- a/services/docstore/test/unit/coffee/HttpControllerTests.js +++ b/services/docstore/test/unit/coffee/HttpControllerTests.js @@ -1,3 +1,9 @@ +/* eslint-disable + no-return-assign, + no-unused-vars, +*/ +// TODO: This file was created by bulk-decaffeinate. +// Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS102: Remove unnecessary code created because of implicit returns @@ -222,7 +228,7 @@ describe("HttpController", function() { }); }); - describe("getAllRanges", () => describe("normally", function() { + describe("getAllRanges", function() { return describe("normally", function() { beforeEach(function() { this.req.params = {project_id: this.project_id}; @@ -254,7 +260,7 @@ describe("HttpController", function() { }]) .should.equal(true); }); - })); + }); }); describe("updateDoc", function() { beforeEach(function() { diff --git a/services/docstore/test/unit/coffee/MongoManagerTests.js b/services/docstore/test/unit/coffee/MongoManagerTests.js index 0832c89d21..d7dabe3afb 100644 --- a/services/docstore/test/unit/coffee/MongoManagerTests.js +++ b/services/docstore/test/unit/coffee/MongoManagerTests.js @@ -1,3 +1,9 @@ +/* eslint-disable + handle-callback-err, + no-return-assign, +*/ +// TODO: This file was created by bulk-decaffeinate. +// Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS102: Remove unnecessary code created because of implicit returns @@ -111,9 +117,9 @@ describe("MongoManager", function() { return this.MongoManager.upsertIntoDocCollection(this.project_id, this.doc_id, {lines: this.lines}, err=> { const args = this.db.docs.update.args[0]; assert.deepEqual(args[0], {_id: ObjectId(this.doc_id)}); - assert.equal(args[1]["$set"]["lines"], this.lines); - assert.equal(args[1]["$inc"]["rev"], 1); - assert.deepEqual(args[1]["$set"]["project_id"], ObjectId(this.project_id)); + assert.equal(args[1].$set.lines, this.lines); + assert.equal(args[1].$inc.rev, 1); + assert.deepEqual(args[1].$set.project_id, ObjectId(this.project_id)); return done(); }); }); @@ -136,7 +142,7 @@ describe("MongoManager", function() { return this.MongoManager.markDocAsDeleted(this.project_id, this.doc_id, err=> { const args = this.db.docs.update.args[0]; assert.deepEqual(args[0], {_id: ObjectId(this.doc_id), project_id: ObjectId(this.project_id)}); - assert.equal(args[1]["$set"]["deleted"], true); + assert.equal(args[1].$set.deleted, true); return done(); }); }); diff --git a/services/docstore/test/unit/coffee/RangeManagerTests.js b/services/docstore/test/unit/coffee/RangeManagerTests.js index f98ca2cbe9..b67e535181 100644 --- a/services/docstore/test/unit/coffee/RangeManagerTests.js +++ b/services/docstore/test/unit/coffee/RangeManagerTests.js @@ -1,3 +1,10 @@ +/* eslint-disable + camelcase, + no-return-assign, + no-unused-vars, +*/ +// TODO: This file was created by bulk-decaffeinate. +// Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS102: Remove unnecessary code created because of implicit returns @@ -137,20 +144,20 @@ describe("RangeManager", function() { return this.ranges_copy = this.RangeManager.jsonRangesToMongo(JSON.parse(JSON.stringify(this.ranges))); }); - describe("with a blank new range", () => it("should throw an error", function() { + describe("with a blank new range", function() { return it("should throw an error", function() { return expect(() => { return this.RangeManager.shouldUpdateRanges(this.ranges, null); }).to.throw(Error); - })); + }); }); - describe("with a blank old range", () => it("should treat it like {}", function() { + describe("with a blank old range", function() { return it("should treat it like {}", function() { this.RangeManager.shouldUpdateRanges(null, {}).should.equal(false); return this.RangeManager.shouldUpdateRanges(null, this.ranges).should.equal(true); - })); + }); }); - describe("with no changes", () => it("should return false", function() { + describe("with no changes", function() { return it("should return false", function() { return this.RangeManager.shouldUpdateRanges(this.ranges, this.ranges_copy).should.equal(false); - })); + }); }); return describe("with changes", function() { it("should return true when the change id changes", function() { From 75f12456105b0253c2b4940af2a2539d7f670f08 Mon Sep 17 00:00:00 2001 From: Simon Detheridge Date: Sun, 16 Feb 2020 14:02:52 +0000 Subject: [PATCH 12/27] decaffeinate: rename test/unit/coffee to test/unit/js --- .../docstore/test/unit/{coffee => js}/DocArchiveManagerTests.js | 0 services/docstore/test/unit/{coffee => js}/DocManagerTests.js | 0 services/docstore/test/unit/{coffee => js}/HttpControllerTests.js | 0 services/docstore/test/unit/{coffee => js}/MongoManagerTests.js | 0 services/docstore/test/unit/{coffee => js}/RangeManagerTests.js | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename services/docstore/test/unit/{coffee => js}/DocArchiveManagerTests.js (100%) rename services/docstore/test/unit/{coffee => js}/DocManagerTests.js (100%) rename services/docstore/test/unit/{coffee => js}/HttpControllerTests.js (100%) rename services/docstore/test/unit/{coffee => js}/MongoManagerTests.js (100%) rename services/docstore/test/unit/{coffee => js}/RangeManagerTests.js (100%) diff --git a/services/docstore/test/unit/coffee/DocArchiveManagerTests.js b/services/docstore/test/unit/js/DocArchiveManagerTests.js similarity index 100% rename from services/docstore/test/unit/coffee/DocArchiveManagerTests.js rename to services/docstore/test/unit/js/DocArchiveManagerTests.js diff --git a/services/docstore/test/unit/coffee/DocManagerTests.js b/services/docstore/test/unit/js/DocManagerTests.js similarity index 100% rename from services/docstore/test/unit/coffee/DocManagerTests.js rename to services/docstore/test/unit/js/DocManagerTests.js diff --git a/services/docstore/test/unit/coffee/HttpControllerTests.js b/services/docstore/test/unit/js/HttpControllerTests.js similarity index 100% rename from services/docstore/test/unit/coffee/HttpControllerTests.js rename to services/docstore/test/unit/js/HttpControllerTests.js diff --git a/services/docstore/test/unit/coffee/MongoManagerTests.js b/services/docstore/test/unit/js/MongoManagerTests.js similarity index 100% rename from services/docstore/test/unit/coffee/MongoManagerTests.js rename to services/docstore/test/unit/js/MongoManagerTests.js diff --git a/services/docstore/test/unit/coffee/RangeManagerTests.js b/services/docstore/test/unit/js/RangeManagerTests.js similarity index 100% rename from services/docstore/test/unit/coffee/RangeManagerTests.js rename to services/docstore/test/unit/js/RangeManagerTests.js From 088fd29391335b9b7323e4e2d49362dcc09901e0 Mon Sep 17 00:00:00 2001 From: Simon Detheridge Date: Sun, 16 Feb 2020 14:02:55 +0000 Subject: [PATCH 13/27] prettier: convert test/unit decaffeinated files to Prettier format --- .../test/unit/js/DocArchiveManagerTests.js | 911 +++++++----- .../docstore/test/unit/js/DocManagerTests.js | 1325 ++++++++++------- .../test/unit/js/HttpControllerTests.js | 821 +++++----- .../test/unit/js/MongoManagerTests.js | 450 +++--- .../test/unit/js/RangeManagerTests.js | 414 ++--- 5 files changed, 2233 insertions(+), 1688 deletions(-) diff --git a/services/docstore/test/unit/js/DocArchiveManagerTests.js b/services/docstore/test/unit/js/DocArchiveManagerTests.js index 97cfa73140..06bd6db8aa 100644 --- a/services/docstore/test/unit/js/DocArchiveManagerTests.js +++ b/services/docstore/test/unit/js/DocArchiveManagerTests.js @@ -12,441 +12,566 @@ * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const { - assert -} = require("chai"); -const sinon = require('sinon'); -const chai = require('chai'); -const should = chai.should(); -const { - expect -} = chai; -const modulePath = "../../../app/js/DocArchiveManager.js"; -const SandboxedModule = require('sandboxed-module'); -const { - ObjectId -} = require("mongojs"); -const Errors = require("../../../app/js/Errors"); -const crypto = require("crypto"); +const { assert } = require('chai') +const sinon = require('sinon') +const chai = require('chai') +const should = chai.should() +const { expect } = chai +const modulePath = '../../../app/js/DocArchiveManager.js' +const SandboxedModule = require('sandboxed-module') +const { ObjectId } = require('mongojs') +const Errors = require('../../../app/js/Errors') +const crypto = require('crypto') -describe("DocArchiveManager", function() { +describe('DocArchiveManager', function() { + beforeEach(function() { + this.settings = { + docstore: { + s3: { + secret: 'secret', + key: 'this_key', + bucket: 'doc-archive-unit-test' + } + } + } - beforeEach(function() { + this.request = { + put: {}, + get: {}, + del: {} + } - this.settings = { - docstore: { - s3: { - secret: "secret", - key: "this_key", - bucket:"doc-archive-unit-test" - } - } - }; + this.archivedDocs = [ + { + _id: ObjectId(), + inS3: true, + rev: 2 + }, + { + _id: ObjectId(), + inS3: true, + rev: 4 + }, + { + _id: ObjectId(), + inS3: true, + rev: 6 + } + ] - this.request = { - put: {}, - get: {}, - del: {} - }; + this.mongoDocs = [ + { + _id: ObjectId(), + lines: ['one', 'two', 'three'], + rev: 2 + }, + { + _id: ObjectId(), + lines: ['aaa', 'bbb', 'ccc'], + rev: 4 + }, + { + _id: ObjectId(), + inS3: true, + rev: 6 + }, + { + _id: ObjectId(), + inS3: true, + rev: 6 + }, + { + _id: ObjectId(), + lines: ['111', '222', '333'], + rev: 6 + } + ] - this.archivedDocs = [{ - _id: ObjectId(), - inS3:true, - rev: 2 - }, { - _id: ObjectId(), - inS3:true, - rev: 4 - }, { - _id: ObjectId(), - inS3:true, - rev: 6 - }]; + this.unarchivedDocs = [ + { + _id: ObjectId(), + lines: ['wombat', 'potato', 'banana'], + rev: 2 + }, + { + _id: ObjectId(), + lines: ['llama', 'turnip', 'apple'], + rev: 4 + }, + { + _id: ObjectId(), + lines: ['elephant', 'swede', 'nectarine'], + rev: 6 + } + ] - this.mongoDocs = [{ - _id: ObjectId(), - lines: ["one", "two", "three"], - rev: 2 - }, { - _id: ObjectId(), - lines: ["aaa", "bbb", "ccc"], - rev: 4 - }, { - _id: ObjectId(), - inS3: true, - rev: 6 - }, { - _id: ObjectId(), - inS3: true, - rev: 6 - }, { - _id: ObjectId(), - lines: ["111", "222", "333"], - rev: 6 - }]; + this.mixedDocs = this.archivedDocs.concat(this.unarchivedDocs) - this.unarchivedDocs = [{ - _id: ObjectId(), - lines: ["wombat", "potato", "banana"], - rev: 2 - }, { - _id: ObjectId(), - lines: ["llama", "turnip", "apple"], - rev: 4 - }, { - _id: ObjectId(), - lines: ["elephant", "swede", "nectarine"], - rev: 6 - }]; + this.MongoManager = { + markDocAsArchived: sinon.stub().callsArgWith(2, null), + upsertIntoDocCollection: sinon.stub().callsArgWith(3, null), + getProjectsDocs: sinon.stub().callsArgWith(3, null, this.mongoDocs), + getArchivedProjectDocs: sinon.stub().callsArgWith(2, null, this.mongoDocs) + } - this.mixedDocs = this.archivedDocs.concat(this.unarchivedDocs); + this.requires = { + 'settings-sharelatex': this.settings, + './MongoManager': this.MongoManager, + request: this.request, + './RangeManager': (this.RangeManager = {}), + 'logger-sharelatex': { + log() {}, + err() {} + } + } + this.globals = { JSON } - this.MongoManager = { - markDocAsArchived: sinon.stub().callsArgWith(2, null), - upsertIntoDocCollection: sinon.stub().callsArgWith(3, null), - getProjectsDocs: sinon.stub().callsArgWith(3, null, this.mongoDocs), - getArchivedProjectDocs: sinon.stub().callsArgWith(2, null, this.mongoDocs) - }; + this.error = 'my errror' + this.project_id = ObjectId().toString() + this.stubbedError = new Errors.NotFoundError('Error in S3 request') + return (this.DocArchiveManager = SandboxedModule.require(modulePath, { + requires: this.requires, + globals: this.globals + })) + }) - this.requires = { - "settings-sharelatex": this.settings, - "./MongoManager": this.MongoManager, - "request": this.request, - "./RangeManager": (this.RangeManager = {}), - "logger-sharelatex": { - log() {}, - err() {} - } - }; - this.globals = - {JSON}; + describe('archiveDoc', function() { + it('should use correct options', function(done) { + this.request.put = sinon + .stub() + .callsArgWith(1, null, { statusCode: 200, headers: { etag: '' } }) + return this.DocArchiveManager.archiveDoc( + this.project_id, + this.mongoDocs[0], + err => { + const opts = this.request.put.args[0][0] + assert.deepEqual(opts.aws, { + key: this.settings.docstore.s3.key, + secret: this.settings.docstore.s3.secret, + bucket: this.settings.docstore.s3.bucket + }) + opts.body.should.equal( + JSON.stringify({ + lines: this.mongoDocs[0].lines, + ranges: this.mongoDocs[0].ranges, + schema_v: 1 + }) + ) + opts.timeout.should.equal(30 * 1000) + opts.uri.should.equal( + `https://${this.settings.docstore.s3.bucket}.s3.amazonaws.com/${this.project_id}/${this.mongoDocs[0]._id}` + ) + return done() + } + ) + }) - this.error = "my errror"; - this.project_id = ObjectId().toString(); - this.stubbedError = new Errors.NotFoundError("Error in S3 request"); - return this.DocArchiveManager = SandboxedModule.require(modulePath, {requires: this.requires, globals: this.globals}); - }); + it('should return no md5 error', function(done) { + const data = JSON.stringify({ + lines: this.mongoDocs[0].lines, + ranges: this.mongoDocs[0].ranges, + schema_v: 1 + }) + this.md5 = crypto + .createHash('md5') + .update(data) + .digest('hex') + this.request.put = sinon + .stub() + .callsArgWith(1, null, { statusCode: 200, headers: { etag: this.md5 } }) + return this.DocArchiveManager.archiveDoc( + this.project_id, + this.mongoDocs[0], + err => { + should.not.exist(err) + return done() + } + ) + }) - describe("archiveDoc", function() { + return it('should return the error', function(done) { + this.request.put = sinon.stub().callsArgWith(1, this.stubbedError, { + statusCode: 400, + headers: { etag: '' } + }) + return this.DocArchiveManager.archiveDoc( + this.project_id, + this.mongoDocs[0], + err => { + should.exist(err) + return done() + } + ) + }) + }) - it("should use correct options", function(done){ - this.request.put = sinon.stub().callsArgWith(1, null, {statusCode:200,headers:{etag:""}}); - return this.DocArchiveManager.archiveDoc(this.project_id, this.mongoDocs[0], err=> { - const opts = this.request.put.args[0][0]; - assert.deepEqual(opts.aws, {key:this.settings.docstore.s3.key, secret:this.settings.docstore.s3.secret, bucket:this.settings.docstore.s3.bucket}); - opts.body.should.equal(JSON.stringify({ - lines: this.mongoDocs[0].lines, - ranges: this.mongoDocs[0].ranges, - schema_v: 1 - }) - ); - opts.timeout.should.equal((30*1000)); - opts.uri.should.equal(`https://${this.settings.docstore.s3.bucket}.s3.amazonaws.com/${this.project_id}/${this.mongoDocs[0]._id}`); - return done(); - }); - }); + describe('unarchiveDoc', function() { + it('should use correct options', function(done) { + this.request.get = sinon + .stub() + .callsArgWith(1, null, { statusCode: 200 }, this.mongoDocs[0].lines) + this.request.del = sinon + .stub() + .callsArgWith(1, null, { statusCode: 204 }, {}) + return this.DocArchiveManager.unarchiveDoc( + this.project_id, + this.mongoDocs[0]._id, + err => { + const opts = this.request.get.args[0][0] + assert.deepEqual(opts.aws, { + key: this.settings.docstore.s3.key, + secret: this.settings.docstore.s3.secret, + bucket: this.settings.docstore.s3.bucket + }) + opts.json.should.equal(true) + opts.timeout.should.equal(30 * 1000) + opts.uri.should.equal( + `https://${this.settings.docstore.s3.bucket}.s3.amazonaws.com/${this.project_id}/${this.mongoDocs[0]._id}` + ) + return done() + } + ) + }) - it("should return no md5 error", function(done){ - const data = JSON.stringify({ - lines: this.mongoDocs[0].lines, - ranges: this.mongoDocs[0].ranges, - schema_v: 1 - }); - this.md5 = crypto.createHash("md5").update(data).digest("hex"); - this.request.put = sinon.stub().callsArgWith(1, null, {statusCode:200,headers:{etag:this.md5}}); - return this.DocArchiveManager.archiveDoc(this.project_id, this.mongoDocs[0], err=> { - should.not.exist(err); - return done(); - }); - }); + it('should return the error', function(done) { + this.request.get = sinon.stub().callsArgWith(1, this.stubbedError, {}, {}) + return this.DocArchiveManager.unarchiveDoc( + this.project_id, + this.mongoDocs[0], + err => { + should.exist(err) + return done() + } + ) + }) - return it("should return the error", function(done){ - this.request.put = sinon.stub().callsArgWith(1, this.stubbedError, {statusCode:400,headers:{etag:""}}); - return this.DocArchiveManager.archiveDoc(this.project_id, this.mongoDocs[0], err=> { - should.exist(err); - return done(); - }); - }); - }); + return it('should error if the doc lines are a string not an array', function(done) { + this.request.get = sinon + .stub() + .callsArgWith(1, null, { statusCode: 200 }, 'this is a string') + this.request.del = sinon.stub() + return this.DocArchiveManager.unarchiveDoc( + this.project_id, + this.mongoDocs[0], + err => { + should.exist(err) + this.request.del.called.should.equal(false) + return done() + } + ) + }) + }) - describe("unarchiveDoc", function() { + describe('archiveAllDocs', function() { + it('should archive all project docs which are not in s3', function(done) { + this.MongoManager.getProjectsDocs = sinon + .stub() + .callsArgWith(3, null, this.mongoDocs) + this.DocArchiveManager.archiveDoc = sinon.stub().callsArgWith(2, null) - it("should use correct options", function(done){ - this.request.get = sinon.stub().callsArgWith(1, null, {statusCode:200}, this.mongoDocs[0].lines); - this.request.del = sinon.stub().callsArgWith(1, null, {statusCode:204}, {}); - return this.DocArchiveManager.unarchiveDoc(this.project_id, this.mongoDocs[0]._id, err=> { - const opts = this.request.get.args[0][0]; - assert.deepEqual(opts.aws, {key:this.settings.docstore.s3.key, secret:this.settings.docstore.s3.secret, bucket:this.settings.docstore.s3.bucket}); - opts.json.should.equal(true); - opts.timeout.should.equal((30*1000)); - opts.uri.should.equal(`https://${this.settings.docstore.s3.bucket}.s3.amazonaws.com/${this.project_id}/${this.mongoDocs[0]._id}`); - return done(); - }); - }); + return this.DocArchiveManager.archiveAllDocs(this.project_id, err => { + this.DocArchiveManager.archiveDoc + .calledWith(this.project_id, this.mongoDocs[0]) + .should.equal(true) + this.DocArchiveManager.archiveDoc + .calledWith(this.project_id, this.mongoDocs[1]) + .should.equal(true) + this.DocArchiveManager.archiveDoc + .calledWith(this.project_id, this.mongoDocs[4]) + .should.equal(true) - it("should return the error", function(done){ - this.request.get = sinon.stub().callsArgWith(1, this.stubbedError, {}, {}); - return this.DocArchiveManager.unarchiveDoc(this.project_id, this.mongoDocs[0], err=> { - should.exist(err); - return done(); - }); - }); + this.DocArchiveManager.archiveDoc + .calledWith(this.project_id, this.mongoDocs[2]) + .should.equal(false) + this.DocArchiveManager.archiveDoc + .calledWith(this.project_id, this.mongoDocs[3]) + .should.equal(false) - return it("should error if the doc lines are a string not an array", function(done){ - this.request.get = sinon.stub().callsArgWith(1, null, {statusCode:200}, "this is a string"); - this.request.del = sinon.stub(); - return this.DocArchiveManager.unarchiveDoc(this.project_id, this.mongoDocs[0], err=> { - should.exist(err); - this.request.del.called.should.equal(false); - return done(); - }); - }); - }); + should.not.exist(err) + return done() + }) + }) - describe("archiveAllDocs", function() { + it('should return error if have no docs', function(done) { + this.MongoManager.getProjectsDocs = sinon + .stub() + .callsArgWith(3, null, null) - it("should archive all project docs which are not in s3", function(done){ - this.MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, this.mongoDocs); - this.DocArchiveManager.archiveDoc = sinon.stub().callsArgWith(2, null); + return this.DocArchiveManager.archiveAllDocs(this.project_id, err => { + should.exist(err) + return done() + }) + }) - return this.DocArchiveManager.archiveAllDocs(this.project_id, err=> { - this.DocArchiveManager.archiveDoc.calledWith(this.project_id, this.mongoDocs[0]).should.equal(true); - this.DocArchiveManager.archiveDoc.calledWith(this.project_id, this.mongoDocs[1]).should.equal(true); - this.DocArchiveManager.archiveDoc.calledWith(this.project_id, this.mongoDocs[4]).should.equal(true); + it('should return the error', function(done) { + this.MongoManager.getProjectsDocs = sinon + .stub() + .callsArgWith(3, this.error, null) - this.DocArchiveManager.archiveDoc.calledWith(this.project_id, this.mongoDocs[2]).should.equal(false); - this.DocArchiveManager.archiveDoc.calledWith(this.project_id, this.mongoDocs[3]).should.equal(false); - - should.not.exist(err); - return done(); - }); - }); + return this.DocArchiveManager.archiveAllDocs(this.project_id, err => { + err.should.equal(this.error) + return done() + }) + }) - it("should return error if have no docs", function(done){ - this.MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, null); + return describe('when most have been already put in s3', function() { + beforeEach(function() { + let numberOfDocs = 10 * 1000 + this.mongoDocs = [] + while (--numberOfDocs !== 0) { + this.mongoDocs.push({ inS3: true, _id: ObjectId() }) + } - return this.DocArchiveManager.archiveAllDocs(this.project_id, err=> { - should.exist(err); - return done(); - }); - }); + this.MongoManager.getProjectsDocs = sinon + .stub() + .callsArgWith(3, null, this.mongoDocs) + return (this.DocArchiveManager.archiveDoc = sinon + .stub() + .callsArgWith(2, null)) + }) - it("should return the error", function(done){ - this.MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, this.error, null); + return it('should not throw and error', function(done) { + return this.DocArchiveManager.archiveAllDocs(this.project_id, err => { + should.not.exist(err) + return done() + }) + }) + }) + }) - return this.DocArchiveManager.archiveAllDocs(this.project_id, err=> { - err.should.equal(this.error); - return done(); - }); - }); + describe('unArchiveAllDocs', function() { + it('should unarchive all inS3 docs', function(done) { + this.MongoManager.getArchivedProjectDocs = sinon + .stub() + .callsArgWith(1, null, this.archivedDocs) + this.DocArchiveManager.unarchiveDoc = sinon.stub().callsArgWith(2, null) + return this.DocArchiveManager.unArchiveAllDocs(this.project_id, err => { + for (const doc of Array.from(this.archivedDocs)) { + this.DocArchiveManager.unarchiveDoc + .calledWith(this.project_id, doc._id) + .should.equal(true) + } + should.not.exist(err) + return done() + }) + }) - return describe("when most have been already put in s3", function() { + it('should return error if have no docs', function(done) { + this.MongoManager.getArchivedProjectDocs = sinon + .stub() + .callsArgWith(1, null, null) + return this.DocArchiveManager.unArchiveAllDocs(this.project_id, err => { + should.exist(err) + return done() + }) + }) - beforeEach(function() { - let numberOfDocs = 10 * 1000; - this.mongoDocs = []; - while (--numberOfDocs !== 0) { - this.mongoDocs.push({inS3:true, _id: ObjectId()}); - } + return it('should return the error', function(done) { + this.MongoManager.getArchivedProjectDocs = sinon + .stub() + .callsArgWith(1, this.error, null) + return this.DocArchiveManager.unArchiveAllDocs(this.project_id, err => { + err.should.equal(this.error) + return done() + }) + }) + }) - this.MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, this.mongoDocs); - return this.DocArchiveManager.archiveDoc = sinon.stub().callsArgWith(2, null); - }); + describe('destroyAllDocs', function() { + beforeEach(function() { + this.request.del = sinon + .stub() + .callsArgWith(1, null, { statusCode: 204 }, {}) + this.MongoManager.getProjectsDocs = sinon + .stub() + .callsArgWith(3, null, this.mixedDocs) + this.MongoManager.findDoc = sinon.stub().callsArgWith(3, null, null) + this.MongoManager.destroyDoc = sinon.stub().yields() + return Array.from(this.mixedDocs).map(doc => + this.MongoManager.findDoc + .withArgs(this.project_id, doc._id) + .callsArgWith(3, null, doc) + ) + }) - return it("should not throw and error", function(done){ - return this.DocArchiveManager.archiveAllDocs(this.project_id, err=> { - should.not.exist(err); - return done(); - }); - }); - }); - }); + it('should destroy all the docs', function(done) { + this.DocArchiveManager.destroyDoc = sinon.stub().callsArgWith(2, null) + return this.DocArchiveManager.destroyAllDocs(this.project_id, err => { + for (const doc of Array.from(this.mixedDocs)) { + this.DocArchiveManager.destroyDoc + .calledWith(this.project_id, doc._id) + .should.equal(true) + } + should.not.exist(err) + return done() + }) + }) + it('should only the s3 docs from s3', function(done) { + const docOpts = doc => { + return JSON.parse( + JSON.stringify({ + aws: { + key: this.settings.docstore.s3.key, + secret: this.settings.docstore.s3.secret, + bucket: this.settings.docstore.s3.bucket + }, + json: true, + timeout: 30 * 1000, + uri: `https://${this.settings.docstore.s3.bucket}.s3.amazonaws.com/${this.project_id}/${doc._id}` + }) + ) + } - describe("unArchiveAllDocs", function() { + return this.DocArchiveManager.destroyAllDocs(this.project_id, err => { + let doc + expect(err).not.to.exist - it("should unarchive all inS3 docs", function(done){ - this.MongoManager.getArchivedProjectDocs = sinon.stub().callsArgWith(1, null, this.archivedDocs); - this.DocArchiveManager.unarchiveDoc = sinon.stub().callsArgWith(2, null); - return this.DocArchiveManager.unArchiveAllDocs(this.project_id, err=> { - for (const doc of Array.from(this.archivedDocs)) { - this.DocArchiveManager.unarchiveDoc.calledWith(this.project_id, doc._id).should.equal(true); - } - should.not.exist(err); - return done(); - }); - }); + for (doc of Array.from(this.archivedDocs)) { + sinon.assert.calledWith(this.request.del, docOpts(doc)) + } + for (doc of Array.from(this.unarchivedDocs)) { + expect(this.request.del.calledWith(docOpts(doc))).to.equal(false) + } // no notCalledWith - it("should return error if have no docs", function(done){ - this.MongoManager.getArchivedProjectDocs = sinon.stub().callsArgWith(1, null, null); - return this.DocArchiveManager.unArchiveAllDocs(this.project_id, err=> { - should.exist(err); - return done(); - }); - }); + return done() + }) + }) - return it("should return the error", function(done){ - this.MongoManager.getArchivedProjectDocs = sinon.stub().callsArgWith(1, this.error, null); - return this.DocArchiveManager.unArchiveAllDocs(this.project_id, err=> { - err.should.equal(this.error); - return done(); - }); - }); - }); + return it('should remove the docs from mongo', function(done) { + this.DocArchiveManager.destroyAllDocs(this.project_id, err => { + return expect(err).not.to.exist + }) - describe("destroyAllDocs", function() { - beforeEach(function() { - this.request.del = sinon.stub().callsArgWith(1, null, {statusCode:204}, {}); - this.MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, this.mixedDocs); - this.MongoManager.findDoc = sinon.stub().callsArgWith(3, null, null); - this.MongoManager.destroyDoc = sinon.stub().yields(); - return Array.from(this.mixedDocs).map((doc) => - this.MongoManager.findDoc.withArgs(this.project_id, doc._id).callsArgWith(3, null, doc)); - }); + for (const doc of Array.from(this.mixedDocs)) { + sinon.assert.calledWith(this.MongoManager.destroyDoc, doc._id) + } - it("should destroy all the docs", function(done){ - this.DocArchiveManager.destroyDoc = sinon.stub().callsArgWith(2, null); - return this.DocArchiveManager.destroyAllDocs(this.project_id, err=> { - for (const doc of Array.from(this.mixedDocs)) { - this.DocArchiveManager.destroyDoc.calledWith(this.project_id, doc._id).should.equal(true); - } - should.not.exist(err); - return done(); - }); - }); + return done() + }) + }) - it("should only the s3 docs from s3", function(done){ - const docOpts = doc => { - return JSON.parse(JSON.stringify({ - aws: {key:this.settings.docstore.s3.key, secret:this.settings.docstore.s3.secret, bucket:this.settings.docstore.s3.bucket}, - json: true, - timeout: 30 * 1000, - uri:`https://${this.settings.docstore.s3.bucket}.s3.amazonaws.com/${this.project_id}/${doc._id}` - })); - }; + describe('_s3DocToMongoDoc', function() { + describe('with the old schema', function() { + return it('should return the docs lines', function(done) { + return this.DocArchiveManager._s3DocToMongoDoc( + ['doc', 'lines'], + (error, doc) => { + expect(doc).to.deep.equal({ + lines: ['doc', 'lines'] + }) + return done() + } + ) + }) + }) - return this.DocArchiveManager.destroyAllDocs(this.project_id, err=> { - let doc; - expect(err).not.to.exist; + describe('with the new schema', function() { + it('should return the doc lines and ranges', function(done) { + this.RangeManager.jsonRangesToMongo = sinon + .stub() + .returns({ mongo: 'ranges' }) + return this.DocArchiveManager._s3DocToMongoDoc( + { + lines: ['doc', 'lines'], + ranges: { json: 'ranges' }, + schema_v: 1 + }, + (error, doc) => { + expect(doc).to.deep.equal({ + lines: ['doc', 'lines'], + ranges: { mongo: 'ranges' } + }) + return done() + } + ) + }) - for (doc of Array.from(this.archivedDocs)) { - sinon.assert.calledWith(this.request.del, docOpts(doc)); - } - for (doc of Array.from(this.unarchivedDocs)) { - expect(this.request.del.calledWith(docOpts(doc))).to.equal(false); - } // no notCalledWith + return it('should return just the doc lines when there are no ranges', function(done) { + return this.DocArchiveManager._s3DocToMongoDoc( + { + lines: ['doc', 'lines'], + schema_v: 1 + }, + (error, doc) => { + expect(doc).to.deep.equal({ + lines: ['doc', 'lines'] + }) + return done() + } + ) + }) + }) - return done(); - }); - }); + return describe('with an unrecognised schema', function() { + return it('should return an error', function(done) { + return this.DocArchiveManager._s3DocToMongoDoc( + { + schema_v: 2 + }, + (error, doc) => { + expect(error).to.exist + return done() + } + ) + }) + }) + }) - return it("should remove the docs from mongo", function(done){ - this.DocArchiveManager.destroyAllDocs(this.project_id, err=> { - return expect(err).not.to.exist; - }); + return describe('_mongoDocToS3Doc', function() { + describe('with a valid doc', function() { + return it('should return the json version', function(done) { + let doc + return this.DocArchiveManager._mongoDocToS3Doc( + (doc = { + lines: ['doc', 'lines'], + ranges: { mock: 'ranges' } + }), + (err, s3_doc) => { + expect(s3_doc).to.equal( + JSON.stringify({ + lines: ['doc', 'lines'], + ranges: { mock: 'ranges' }, + schema_v: 1 + }) + ) + return done() + } + ) + }) + }) - for (const doc of Array.from(this.mixedDocs)) { - sinon.assert.calledWith(this.MongoManager.destroyDoc, doc._id); - } + describe('with null bytes in the result', function() { + beforeEach(function() { + this._stringify = JSON.stringify + return (JSON.stringify = sinon.stub().returns('{"bad": "\u0000"}')) + }) - return done(); - }); - }); - - describe("_s3DocToMongoDoc", function() { - describe("with the old schema", function() { return it("should return the docs lines", function(done) { - return this.DocArchiveManager._s3DocToMongoDoc(["doc", "lines"], (error, doc) => { - expect(doc).to.deep.equal({ - lines: ["doc", "lines"] - }); - return done(); - }); - }); }); - - describe("with the new schema", function() { - it("should return the doc lines and ranges", function(done) { - this.RangeManager.jsonRangesToMongo = sinon.stub().returns({"mongo": "ranges"}); - return this.DocArchiveManager._s3DocToMongoDoc({ - lines: ["doc", "lines"], - ranges: {"json": "ranges"}, - schema_v: 1 - }, (error, doc) => { - expect(doc).to.deep.equal({ - lines: ["doc", "lines"], - ranges: {"mongo": "ranges"} - }); - return done(); - }); - }); - - return it("should return just the doc lines when there are no ranges", function(done) { - return this.DocArchiveManager._s3DocToMongoDoc({ - lines: ["doc", "lines"], - schema_v: 1 - }, (error, doc) => { - expect(doc).to.deep.equal({ - lines: ["doc", "lines"] - }); - return done(); - }); - }); - }); - - return describe("with an unrecognised schema", function() { return it("should return an error", function(done) { - return this.DocArchiveManager._s3DocToMongoDoc({ - schema_v: 2 - }, (error, doc) => { - expect(error).to.exist; - return done(); - }); - }); }); - }); - - return describe("_mongoDocToS3Doc", function() { - describe("with a valid doc", function() { return it("should return the json version", function(done) { - let doc; - return this.DocArchiveManager._mongoDocToS3Doc((doc = { - lines: ["doc", "lines"], - ranges: { "mock": "ranges" } - }), (err, s3_doc) => { - expect(s3_doc).to.equal(JSON.stringify({ - lines: ["doc", "lines"], - ranges: { "mock": "ranges" }, - schema_v: 1 - }) - ); - return done(); - }); - }); }); - - describe("with null bytes in the result", function() { - beforeEach(function() { - this._stringify = JSON.stringify; - return JSON.stringify = sinon.stub().returns('{"bad": "\u0000"}'); - }); - - afterEach(function() { - return JSON.stringify = this._stringify; - }); - - return it("should return an error", function(done) { - return this.DocArchiveManager._mongoDocToS3Doc({ - lines: ["doc", "lines"], - ranges: { "mock": "ranges" } - }, (err, s3_doc) => { - expect(err).to.exist; - return done(); - }); - }); - }); - - return describe("without doc lines", function() { return it("should return an error", function(done) { - return this.DocArchiveManager._mongoDocToS3Doc({}, (err, s3_doc) => { - expect(err).to.exist; - return done(); - }); - }); }); - }); -}); - - + afterEach(function() { + return (JSON.stringify = this._stringify) + }) + + return it('should return an error', function(done) { + return this.DocArchiveManager._mongoDocToS3Doc( + { + lines: ['doc', 'lines'], + ranges: { mock: 'ranges' } + }, + (err, s3_doc) => { + expect(err).to.exist + return done() + } + ) + }) + }) + + return describe('without doc lines', function() { + return it('should return an error', function(done) { + return this.DocArchiveManager._mongoDocToS3Doc({}, (err, s3_doc) => { + expect(err).to.exist + return done() + }) + }) + }) + }) +}) diff --git a/services/docstore/test/unit/js/DocManagerTests.js b/services/docstore/test/unit/js/DocManagerTests.js index 4130818601..9508e74f2e 100644 --- a/services/docstore/test/unit/js/DocManagerTests.js +++ b/services/docstore/test/unit/js/DocManagerTests.js @@ -12,535 +12,796 @@ * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const SandboxedModule = require('sandboxed-module'); -const sinon = require('sinon'); -const chai = require('chai'); -const { - assert -} = require("chai"); -chai.should(); -const { - expect -} = chai; -const modulePath = require('path').join(__dirname, '../../../app/js/DocManager'); -const { - ObjectId -} = require("mongojs"); -const Errors = require("../../../app/js/Errors"); - -describe("DocManager", function() { - beforeEach(function() { - this.DocManager = SandboxedModule.require(modulePath, { requires: { - "./MongoManager": (this.MongoManager = {}), - "./DocArchiveManager": (this.DocArchiveManager = {}), - "./RangeManager": (this.RangeManager = { - jsonRangesToMongo(r) { return r; }, - shouldUpdateRanges: sinon.stub().returns(false) - }), - "logger-sharelatex": (this.logger = { - log: sinon.stub(), - warn() {}, - err() {} - }) - } - } - ); - this.doc_id = ObjectId().toString(); - this.project_id = ObjectId().toString(); - this.another_project_id = ObjectId().toString(); - this.callback = sinon.stub(); - return this.stubbedError = new Error("blew up"); - }); - - - describe("checkDocExists", function() { - beforeEach(function() { - return this.DocManager._getDoc = sinon.stub(); - }); - - it("should call get doc with a quick filter", function(done){ - this.DocManager._getDoc.callsArgWith(3, null, {_id:this.doc_id}); - return this.DocManager.checkDocExists(this.project_id, this.doc_id, (err, exist)=> { - exist.should.equal(true); - this.DocManager._getDoc.calledWith(this.project_id, this.doc_id, {_id:1, inS3:true}).should.equal(true); - return done(); - }); - }); - - it("should return false when doc is not there", function(done){ - this.DocManager._getDoc.callsArgWith(3, null); - return this.DocManager.checkDocExists(this.project_id, this.doc_id, (err, exist)=> { - exist.should.equal(false); - return done(); - }); - }); - - return it("should return error when get doc errors", function(done){ - this.DocManager._getDoc.callsArgWith(3, "error"); - return this.DocManager.checkDocExists(this.project_id, this.doc_id, (err, exist)=> { - err.should.equal("error"); - return done(); - }); - }); - }); - - describe("getFullDoc", function() { - beforeEach(function() { - this.DocManager._getDoc = sinon.stub(); - return this.doc = { - _id: this.doc_id, - lines:["2134"] - };}); - - it("should call get doc with a quick filter", function(done){ - this.DocManager._getDoc.callsArgWith(3, null, this.doc); - return this.DocManager.getFullDoc(this.project_id, this.doc_id, (err, doc)=> { - doc.should.equal(this.doc); - this.DocManager._getDoc.calledWith(this.project_id, this.doc_id, {lines: true, rev: true, deleted: true, version: true, ranges: true, inS3:true}).should.equal(true); - return done(); - }); - }); - - return it("should return error when get doc errors", function(done){ - this.DocManager._getDoc.callsArgWith(3, "error"); - return this.DocManager.getFullDoc(this.project_id, this.doc_id, (err, exist)=> { - err.should.equal("error"); - return done(); - }); - }); - }); - - describe("getRawDoc", function() { - - beforeEach(function() { - this.DocManager._getDoc = sinon.stub(); - return this.doc = - {lines:["2134"]};}); - - it("should call get doc with a quick filter", function(done){ - this.DocManager._getDoc.callsArgWith(3, null, this.doc); - return this.DocManager.getDocLines(this.project_id, this.doc_id, (err, doc)=> { - doc.should.equal(this.doc); - this.DocManager._getDoc.calledWith(this.project_id, this.doc_id, {lines: true, inS3:true}).should.equal(true); - return done(); - }); - }); - - return it("should return error when get doc errors", function(done){ - this.DocManager._getDoc.callsArgWith(3, "error"); - return this.DocManager.getDocLines(this.project_id, this.doc_id, (err, exist)=> { - err.should.equal("error"); - return done(); - }); - }); - }); - - - - describe("getDoc", function() { - beforeEach(function() { - this.project = { name: "mock-project" }; - this.doc = { _id: this.doc_id, project_id: this.project_id, lines: ["mock-lines"] }; - this.version = 42; - this.MongoManager.findDoc = sinon.stub(); - return this.MongoManager.getDocVersion = sinon.stub().yields(null, this.version); - }); - - describe("when using a filter", function() { - beforeEach(function() { - return this.MongoManager.findDoc.yields(null, this.doc); - }); - - it("should error if inS3 is not set to true", function(done){ - return this.DocManager._getDoc(this.project_id, this.doc_id, {inS3: false}, (err) => { - expect(err).to.exist; - return done(); - }); - }); - - it("should always get inS3 even when no filter is passed", function(done){ - return this.DocManager._getDoc(this.project_id, this.doc_id, undefined, err=> { - this.MongoManager.findDoc.called.should.equal(false); - expect(err).to.exist; - return done(); - }); - }); - - return it("should not error if inS3 is set to true", function(done){ - return this.DocManager._getDoc(this.project_id, this.doc_id, {inS3: true}, (err) => { - expect(err).to.not.exist; - return done(); - }); - }); - }); - - describe("when the doc is in the doc collection", function() { - beforeEach(function() { - this.MongoManager.findDoc.yields(null, this.doc); - return this.DocManager._getDoc(this.project_id, this.doc_id, {version: true, inS3:true}, this.callback); - }); - - it("should get the doc from the doc collection", function() { - return this.MongoManager.findDoc - .calledWith(this.project_id, this.doc_id) - .should.equal(true); - }); - - it("should get the doc version from the docOps collection", function() { - return this.MongoManager.getDocVersion - .calledWith(this.doc_id) - .should.equal(true); - }); - - return it("should return the callback with the doc with the version", function() { - this.callback.called.should.equal(true); - const doc = this.callback.args[0][1]; - doc.lines.should.equal(this.doc.lines); - return doc.version.should.equal(this.version); - }); - }); - - describe("without the version filter", function() { - beforeEach(function() { - this.MongoManager.findDoc.yields(null, this.doc); - return this.DocManager._getDoc(this.project_id, this.doc_id, {version: false, inS3:true}, this.callback); - }); - - return it("should not get the doc version from the docOps collection", function() { - return this.MongoManager.getDocVersion.called.should.equal(false); - }); - }); - - describe("when MongoManager.findDoc errors", function() { - beforeEach(function() { - this.MongoManager.findDoc.yields(this.stubbedError); - return this.DocManager._getDoc(this.project_id, this.doc_id, {version: true, inS3:true}, this.callback); - }); - - return it("should return the error", function() { - return this.callback.calledWith(this.stubbedError).should.equal(true); - }); - }); - - describe("when the doc is archived", function() { - beforeEach(function() { - this.doc = { _id: this.doc_id, project_id: this.project_id, lines: ["mock-lines"], inS3: true }; - this.MongoManager.findDoc.yields(null, this.doc); - this.DocArchiveManager.unarchiveDoc = (project_id, doc_id, callback) => { - this.doc.inS3 = false; - return callback(); - }; - sinon.spy(this.DocArchiveManager, "unarchiveDoc"); - return this.DocManager._getDoc(this.project_id, this.doc_id, {version: true, inS3:true}, this.callback); - }); - - it("should call the DocArchive to unarchive the doc", function() { - return this.DocArchiveManager.unarchiveDoc.calledWith(this.project_id, this.doc_id).should.equal(true); - }); - - it("should look up the doc twice", function() { - return this.MongoManager.findDoc.calledTwice.should.equal(true); - }); - - return it("should return the doc", function() { - return this.callback.calledWith(null, this.doc).should.equal(true); - }); - }); - - return describe("when the doc does not exist in the docs collection", function() { - beforeEach(function() { - this.MongoManager.findDoc = sinon.stub().yields(null, null); - return this.DocManager._getDoc(this.project_id, this.doc_id, {version: true, inS3:true}, this.callback); - }); - - return it("should return a NotFoundError", function() { - return this.callback - .calledWith(sinon.match.has('message', `No such doc: ${this.doc_id} in project ${this.project_id}`)) - .should.equal(true); - }); - }); - }); - - describe("getAllNonDeletedDocs", function() { - describe("when the project exists", function() { - beforeEach(function() { - this.docs = [{ _id: this.doc_id, project_id: this.project_id, lines: ["mock-lines"] }]; - this.MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, this.docs); - this.DocArchiveManager.unArchiveAllDocs = sinon.stub().callsArgWith(1, null, this.docs); - this.filter = { lines: true }; - return this.DocManager.getAllNonDeletedDocs(this.project_id, this.filter, this.callback); - }); - - it("should get the project from the database", function() { - return this.MongoManager.getProjectsDocs - .calledWith(this.project_id, {include_deleted: false}, this.filter) - .should.equal(true); - }); - - return it("should return the docs", function() { - return this.callback.calledWith(null, this.docs).should.equal(true); - }); - }); - - return describe("when there are no docs for the project", function() { - beforeEach(function() { - this.MongoManager.getProjectsDocs = sinon.stub().callsArgWith(3, null, null); - this.DocArchiveManager.unArchiveAllDocs = sinon.stub().callsArgWith(1, null); - return this.DocManager.getAllNonDeletedDocs(this.project_id, this.filter, this.callback); - }); - - return it("should return a NotFoundError", function() { - return this.callback - .calledWith(sinon.match.has('message', `No docs for project ${this.project_id}`)) - .should.equal(true); - }); - }); - }); - - describe("deleteDoc", function() { - describe("when the doc exists", function() { - beforeEach(function() { - this.lines = ["mock", "doc", "lines"]; - this.rev = 77; - this.DocManager.checkDocExists = sinon.stub().callsArgWith(2, null, true); - this.MongoManager.markDocAsDeleted = sinon.stub().callsArg(2); - return this.DocManager.deleteDoc(this.project_id, this.doc_id, this.callback); - }); - - it("should get the doc", function() { - return this.DocManager.checkDocExists - .calledWith(this.project_id, this.doc_id) - .should.equal(true); - }); - - it("should mark doc as deleted", function() { - return this.MongoManager.markDocAsDeleted - .calledWith(this.project_id, this.doc_id) - .should.equal(true); - }); - - return it("should return the callback", function() { - return this.callback.called.should.equal(true); - }); - }); - - return describe("when the doc does not exist", function() { - beforeEach(function() { - this.DocManager.checkDocExists = sinon.stub().callsArgWith(2, null, false); - return this.DocManager.deleteDoc(this.project_id, this.doc_id, this.callback); - }); - - return it("should return a NotFoundError", function() { - return this.callback - .calledWith(sinon.match.has('message', `No such project/doc to delete: ${this.project_id}/${this.doc_id}`)) - .should.equal(true); - }); - }); - }); - - return describe("updateDoc", function() { - beforeEach(function() { - this.oldDocLines = ["old", "doc", "lines"]; - this.newDocLines = ["new", "doc", "lines"]; - this.originalRanges = { - changes: [{ - id: ObjectId().toString(), - op: { i: "foo", p: 3 }, - meta: { - user_id: ObjectId().toString(), - ts: new Date().toString() - } - }] - }; - this.newRanges = { - changes: [{ - id: ObjectId().toString(), - op: { i: "bar", p: 6 }, - meta: { - user_id: ObjectId().toString(), - ts: new Date().toString() - } - }] - }; - this.version = 42; - this.doc = { _id: this.doc_id, project_id: this.project_id, lines: this.oldDocLines, rev: (this.rev = 5), version: this.version, ranges: this.originalRanges }; - - this.MongoManager.upsertIntoDocCollection = sinon.stub().callsArg(3); - this.MongoManager.setDocVersion = sinon.stub().yields(); - return this.DocManager._getDoc = sinon.stub(); - }); - - describe("when only the doc lines have changed", function() { - beforeEach(function() { - this.DocManager._getDoc = sinon.stub().callsArgWith(3, null, this.doc); - return this.DocManager.updateDoc(this.project_id, this.doc_id, this.newDocLines, this.version, this.originalRanges, this.callback); - }); - - it("should get the existing doc", function() { - return this.DocManager._getDoc - .calledWith(this.project_id, this.doc_id, {version: true, rev: true, lines: true, version: true, ranges: true, inS3:true}) - .should.equal(true); - }); - - it("should upsert the document to the doc collection", function() { - return this.MongoManager.upsertIntoDocCollection - .calledWith(this.project_id, this.doc_id, {lines: this.newDocLines}) - .should.equal(true); - }); - - it("should not update the version", function() { - return this.MongoManager.setDocVersion.called.should.equal(false); - }); - - return it("should return the callback with the new rev", function() { - return this.callback.calledWith(null, true, this.rev + 1).should.equal(true); - }); - }); - - describe("when the doc ranges have changed", function() { - beforeEach(function() { - this.DocManager._getDoc = sinon.stub().callsArgWith(3, null, this.doc); - this.RangeManager.shouldUpdateRanges.returns(true); - return this.DocManager.updateDoc(this.project_id, this.doc_id, this.oldDocLines, this.version, this.newRanges, this.callback); - }); - - it("should upsert the ranges", function() { - return this.MongoManager.upsertIntoDocCollection - .calledWith(this.project_id, this.doc_id, {ranges: this.newRanges}) - .should.equal(true); - }); - - it("should not update the version", function() { - return this.MongoManager.setDocVersion.called.should.equal(false); - }); - - return it("should return the callback with the new rev", function() { - return this.callback.calledWith(null, true, this.rev + 1).should.equal(true); - }); - }); - - describe("when only the version has changed", function() { - beforeEach(function() { - this.DocManager._getDoc = sinon.stub().callsArgWith(3, null, this.doc); - return this.DocManager.updateDoc(this.project_id, this.doc_id, this.oldDocLines, this.version + 1, this.originalRanges, this.callback); - }); - - it("should not change the lines or ranges", function() { - return this.MongoManager.upsertIntoDocCollection.called.should.equal(false); - }); - - it("should update the version", function() { - return this.MongoManager.setDocVersion - .calledWith(this.doc_id, this.version + 1) - .should.equal(true); - }); - - return it("should return the callback with the old rev", function() { - return this.callback.calledWith(null, true, this.rev).should.equal(true); - }); - }); - - describe("when the doc has not changed at all", function() { - beforeEach(function() { - this.DocManager._getDoc = sinon.stub().callsArgWith(3, null, this.doc); - return this.DocManager.updateDoc(this.project_id, this.doc_id, this.oldDocLines, this.version, this.originalRanges, this.callback); - }); - - it("should not update the ranges or lines", function() { - return this.MongoManager.upsertIntoDocCollection.called.should.equal(false); - }); - - it("should not update the version", function() { - return this.MongoManager.setDocVersion.called.should.equal(false); - }); - - return it("should return the callback with the old rev and modified == false", function() { - return this.callback.calledWith(null, false, this.rev).should.equal(true); - }); - }); - - describe("when the version is null", function() { - beforeEach(function() { - return this.DocManager.updateDoc(this.project_id, this.doc_id, this.newDocLines, null, this.originalRanges, this.callback); - }); - - return it("should return an error", function() { - return this.callback.calledWith(sinon.match.has('message', "no lines, version or ranges provided")).should.equal(true); - }); - }); - - describe("when the lines are null", function() { - beforeEach(function() { - return this.DocManager.updateDoc(this.project_id, this.doc_id, null, this.version, this.originalRanges, this.callback); - }); - - return it("should return an error", function() { - return this.callback.calledWith(sinon.match.has('message', "no lines, version or ranges provided")).should.equal(true); - }); - }); - - describe("when the ranges are null", function() { - beforeEach(function() { - return this.DocManager.updateDoc(this.project_id, this.doc_id, this.newDocLines, this.version, null, this.callback); - }); - - return it("should return an error", function() { - return this.callback.calledWith(sinon.match.has('message', "no lines, version or ranges provided")).should.equal(true); - }); - }); - - describe("when there is a generic error getting the doc", function() { - beforeEach(function() { - this.error = new Error("doc could not be found"); - this.DocManager._getDoc = sinon.stub().callsArgWith(3, this.error, null, null); - return this.DocManager.updateDoc(this.project_id, this.doc_id, this.newDocLines, this.version, this.originalRanges, this.callback); - }); - - it("should not upsert the document to the doc collection", function() { - return this.MongoManager.upsertIntoDocCollection.called.should.equal(false); - }); - - return it("should return the callback with the error", function() { - return this.callback.calledWith(this.error).should.equal(true); - }); - }); - - describe("when the doc lines have not changed", function() { - beforeEach(function() { - this.DocManager._getDoc = sinon.stub().callsArgWith(3, null, this.doc); - return this.DocManager.updateDoc(this.project_id, this.doc_id, this.oldDocLines.slice(), this.version, this.originalRanges, this.callback); - }); - - it("should not update the doc", function() { - return this.MongoManager.upsertIntoDocCollection.called.should.equal(false); - }); - - return it("should return the callback with the existing rev", function() { - return this.callback.calledWith(null, false, this.rev).should.equal(true); - }); - }); - - return describe("when the doc does not exist", function() { - beforeEach(function() { - this.DocManager._getDoc = sinon.stub().callsArgWith(3, null, null, null); - return this.DocManager.updateDoc(this.project_id, this.doc_id, this.newDocLines, this.version, this.originalRanges, this.callback); - }); - - it("should upsert the document to the doc collection", function() { - return this.MongoManager.upsertIntoDocCollection - .calledWith(this.project_id, this.doc_id, {lines: this.newDocLines, ranges: this.originalRanges}) - .should.equal(true); - }); - - it("should set the version", function() { - return this.MongoManager.setDocVersion - .calledWith(this.doc_id, this.version) - .should.equal(true); - }); - - return it("should return the callback with the new rev", function() { - return this.callback.calledWith(null, true, 1).should.equal(true); - }); - }); - }); -}); +const SandboxedModule = require('sandboxed-module') +const sinon = require('sinon') +const chai = require('chai') +const { assert } = require('chai') +chai.should() +const { expect } = chai +const modulePath = require('path').join(__dirname, '../../../app/js/DocManager') +const { ObjectId } = require('mongojs') +const Errors = require('../../../app/js/Errors') + +describe('DocManager', function() { + beforeEach(function() { + this.DocManager = SandboxedModule.require(modulePath, { + requires: { + './MongoManager': (this.MongoManager = {}), + './DocArchiveManager': (this.DocArchiveManager = {}), + './RangeManager': (this.RangeManager = { + jsonRangesToMongo(r) { + return r + }, + shouldUpdateRanges: sinon.stub().returns(false) + }), + 'logger-sharelatex': (this.logger = { + log: sinon.stub(), + warn() {}, + err() {} + }) + } + }) + this.doc_id = ObjectId().toString() + this.project_id = ObjectId().toString() + this.another_project_id = ObjectId().toString() + this.callback = sinon.stub() + return (this.stubbedError = new Error('blew up')) + }) + + describe('checkDocExists', function() { + beforeEach(function() { + return (this.DocManager._getDoc = sinon.stub()) + }) + + it('should call get doc with a quick filter', function(done) { + this.DocManager._getDoc.callsArgWith(3, null, { _id: this.doc_id }) + return this.DocManager.checkDocExists( + this.project_id, + this.doc_id, + (err, exist) => { + exist.should.equal(true) + this.DocManager._getDoc + .calledWith(this.project_id, this.doc_id, { _id: 1, inS3: true }) + .should.equal(true) + return done() + } + ) + }) + + it('should return false when doc is not there', function(done) { + this.DocManager._getDoc.callsArgWith(3, null) + return this.DocManager.checkDocExists( + this.project_id, + this.doc_id, + (err, exist) => { + exist.should.equal(false) + return done() + } + ) + }) + + return it('should return error when get doc errors', function(done) { + this.DocManager._getDoc.callsArgWith(3, 'error') + return this.DocManager.checkDocExists( + this.project_id, + this.doc_id, + (err, exist) => { + err.should.equal('error') + return done() + } + ) + }) + }) + + describe('getFullDoc', function() { + beforeEach(function() { + this.DocManager._getDoc = sinon.stub() + return (this.doc = { + _id: this.doc_id, + lines: ['2134'] + }) + }) + + it('should call get doc with a quick filter', function(done) { + this.DocManager._getDoc.callsArgWith(3, null, this.doc) + return this.DocManager.getFullDoc( + this.project_id, + this.doc_id, + (err, doc) => { + doc.should.equal(this.doc) + this.DocManager._getDoc + .calledWith(this.project_id, this.doc_id, { + lines: true, + rev: true, + deleted: true, + version: true, + ranges: true, + inS3: true + }) + .should.equal(true) + return done() + } + ) + }) + + return it('should return error when get doc errors', function(done) { + this.DocManager._getDoc.callsArgWith(3, 'error') + return this.DocManager.getFullDoc( + this.project_id, + this.doc_id, + (err, exist) => { + err.should.equal('error') + return done() + } + ) + }) + }) + + describe('getRawDoc', function() { + beforeEach(function() { + this.DocManager._getDoc = sinon.stub() + return (this.doc = { lines: ['2134'] }) + }) + + it('should call get doc with a quick filter', function(done) { + this.DocManager._getDoc.callsArgWith(3, null, this.doc) + return this.DocManager.getDocLines( + this.project_id, + this.doc_id, + (err, doc) => { + doc.should.equal(this.doc) + this.DocManager._getDoc + .calledWith(this.project_id, this.doc_id, { + lines: true, + inS3: true + }) + .should.equal(true) + return done() + } + ) + }) + + return it('should return error when get doc errors', function(done) { + this.DocManager._getDoc.callsArgWith(3, 'error') + return this.DocManager.getDocLines( + this.project_id, + this.doc_id, + (err, exist) => { + err.should.equal('error') + return done() + } + ) + }) + }) + + describe('getDoc', function() { + beforeEach(function() { + this.project = { name: 'mock-project' } + this.doc = { + _id: this.doc_id, + project_id: this.project_id, + lines: ['mock-lines'] + } + this.version = 42 + this.MongoManager.findDoc = sinon.stub() + return (this.MongoManager.getDocVersion = sinon + .stub() + .yields(null, this.version)) + }) + + describe('when using a filter', function() { + beforeEach(function() { + return this.MongoManager.findDoc.yields(null, this.doc) + }) + + it('should error if inS3 is not set to true', function(done) { + return this.DocManager._getDoc( + this.project_id, + this.doc_id, + { inS3: false }, + err => { + expect(err).to.exist + return done() + } + ) + }) + + it('should always get inS3 even when no filter is passed', function(done) { + return this.DocManager._getDoc( + this.project_id, + this.doc_id, + undefined, + err => { + this.MongoManager.findDoc.called.should.equal(false) + expect(err).to.exist + return done() + } + ) + }) + + return it('should not error if inS3 is set to true', function(done) { + return this.DocManager._getDoc( + this.project_id, + this.doc_id, + { inS3: true }, + err => { + expect(err).to.not.exist + return done() + } + ) + }) + }) + + describe('when the doc is in the doc collection', function() { + beforeEach(function() { + this.MongoManager.findDoc.yields(null, this.doc) + return this.DocManager._getDoc( + this.project_id, + this.doc_id, + { version: true, inS3: true }, + this.callback + ) + }) + + it('should get the doc from the doc collection', function() { + return this.MongoManager.findDoc + .calledWith(this.project_id, this.doc_id) + .should.equal(true) + }) + + it('should get the doc version from the docOps collection', function() { + return this.MongoManager.getDocVersion + .calledWith(this.doc_id) + .should.equal(true) + }) + + return it('should return the callback with the doc with the version', function() { + this.callback.called.should.equal(true) + const doc = this.callback.args[0][1] + doc.lines.should.equal(this.doc.lines) + return doc.version.should.equal(this.version) + }) + }) + + describe('without the version filter', function() { + beforeEach(function() { + this.MongoManager.findDoc.yields(null, this.doc) + return this.DocManager._getDoc( + this.project_id, + this.doc_id, + { version: false, inS3: true }, + this.callback + ) + }) + + return it('should not get the doc version from the docOps collection', function() { + return this.MongoManager.getDocVersion.called.should.equal(false) + }) + }) + + describe('when MongoManager.findDoc errors', function() { + beforeEach(function() { + this.MongoManager.findDoc.yields(this.stubbedError) + return this.DocManager._getDoc( + this.project_id, + this.doc_id, + { version: true, inS3: true }, + this.callback + ) + }) + + return it('should return the error', function() { + return this.callback.calledWith(this.stubbedError).should.equal(true) + }) + }) + + describe('when the doc is archived', function() { + beforeEach(function() { + this.doc = { + _id: this.doc_id, + project_id: this.project_id, + lines: ['mock-lines'], + inS3: true + } + this.MongoManager.findDoc.yields(null, this.doc) + this.DocArchiveManager.unarchiveDoc = ( + project_id, + doc_id, + callback + ) => { + this.doc.inS3 = false + return callback() + } + sinon.spy(this.DocArchiveManager, 'unarchiveDoc') + return this.DocManager._getDoc( + this.project_id, + this.doc_id, + { version: true, inS3: true }, + this.callback + ) + }) + + it('should call the DocArchive to unarchive the doc', function() { + return this.DocArchiveManager.unarchiveDoc + .calledWith(this.project_id, this.doc_id) + .should.equal(true) + }) + + it('should look up the doc twice', function() { + return this.MongoManager.findDoc.calledTwice.should.equal(true) + }) + + return it('should return the doc', function() { + return this.callback.calledWith(null, this.doc).should.equal(true) + }) + }) + + return describe('when the doc does not exist in the docs collection', function() { + beforeEach(function() { + this.MongoManager.findDoc = sinon.stub().yields(null, null) + return this.DocManager._getDoc( + this.project_id, + this.doc_id, + { version: true, inS3: true }, + this.callback + ) + }) + + return it('should return a NotFoundError', function() { + return this.callback + .calledWith( + sinon.match.has( + 'message', + `No such doc: ${this.doc_id} in project ${this.project_id}` + ) + ) + .should.equal(true) + }) + }) + }) + + describe('getAllNonDeletedDocs', function() { + describe('when the project exists', function() { + beforeEach(function() { + this.docs = [ + { + _id: this.doc_id, + project_id: this.project_id, + lines: ['mock-lines'] + } + ] + this.MongoManager.getProjectsDocs = sinon + .stub() + .callsArgWith(3, null, this.docs) + this.DocArchiveManager.unArchiveAllDocs = sinon + .stub() + .callsArgWith(1, null, this.docs) + this.filter = { lines: true } + return this.DocManager.getAllNonDeletedDocs( + this.project_id, + this.filter, + this.callback + ) + }) + + it('should get the project from the database', function() { + return this.MongoManager.getProjectsDocs + .calledWith(this.project_id, { include_deleted: false }, this.filter) + .should.equal(true) + }) + + return it('should return the docs', function() { + return this.callback.calledWith(null, this.docs).should.equal(true) + }) + }) + + return describe('when there are no docs for the project', function() { + beforeEach(function() { + this.MongoManager.getProjectsDocs = sinon + .stub() + .callsArgWith(3, null, null) + this.DocArchiveManager.unArchiveAllDocs = sinon + .stub() + .callsArgWith(1, null) + return this.DocManager.getAllNonDeletedDocs( + this.project_id, + this.filter, + this.callback + ) + }) + + return it('should return a NotFoundError', function() { + return this.callback + .calledWith( + sinon.match.has('message', `No docs for project ${this.project_id}`) + ) + .should.equal(true) + }) + }) + }) + + describe('deleteDoc', function() { + describe('when the doc exists', function() { + beforeEach(function() { + this.lines = ['mock', 'doc', 'lines'] + this.rev = 77 + this.DocManager.checkDocExists = sinon + .stub() + .callsArgWith(2, null, true) + this.MongoManager.markDocAsDeleted = sinon.stub().callsArg(2) + return this.DocManager.deleteDoc( + this.project_id, + this.doc_id, + this.callback + ) + }) + + it('should get the doc', function() { + return this.DocManager.checkDocExists + .calledWith(this.project_id, this.doc_id) + .should.equal(true) + }) + + it('should mark doc as deleted', function() { + return this.MongoManager.markDocAsDeleted + .calledWith(this.project_id, this.doc_id) + .should.equal(true) + }) + + return it('should return the callback', function() { + return this.callback.called.should.equal(true) + }) + }) + + return describe('when the doc does not exist', function() { + beforeEach(function() { + this.DocManager.checkDocExists = sinon + .stub() + .callsArgWith(2, null, false) + return this.DocManager.deleteDoc( + this.project_id, + this.doc_id, + this.callback + ) + }) + + return it('should return a NotFoundError', function() { + return this.callback + .calledWith( + sinon.match.has( + 'message', + `No such project/doc to delete: ${this.project_id}/${this.doc_id}` + ) + ) + .should.equal(true) + }) + }) + }) + + return describe('updateDoc', function() { + beforeEach(function() { + this.oldDocLines = ['old', 'doc', 'lines'] + this.newDocLines = ['new', 'doc', 'lines'] + this.originalRanges = { + changes: [ + { + id: ObjectId().toString(), + op: { i: 'foo', p: 3 }, + meta: { + user_id: ObjectId().toString(), + ts: new Date().toString() + } + } + ] + } + this.newRanges = { + changes: [ + { + id: ObjectId().toString(), + op: { i: 'bar', p: 6 }, + meta: { + user_id: ObjectId().toString(), + ts: new Date().toString() + } + } + ] + } + this.version = 42 + this.doc = { + _id: this.doc_id, + project_id: this.project_id, + lines: this.oldDocLines, + rev: (this.rev = 5), + version: this.version, + ranges: this.originalRanges + } + + this.MongoManager.upsertIntoDocCollection = sinon.stub().callsArg(3) + this.MongoManager.setDocVersion = sinon.stub().yields() + return (this.DocManager._getDoc = sinon.stub()) + }) + + describe('when only the doc lines have changed', function() { + beforeEach(function() { + this.DocManager._getDoc = sinon.stub().callsArgWith(3, null, this.doc) + return this.DocManager.updateDoc( + this.project_id, + this.doc_id, + this.newDocLines, + this.version, + this.originalRanges, + this.callback + ) + }) + + it('should get the existing doc', function() { + return this.DocManager._getDoc + .calledWith(this.project_id, this.doc_id, { + version: true, + rev: true, + lines: true, + version: true, + ranges: true, + inS3: true + }) + .should.equal(true) + }) + + it('should upsert the document to the doc collection', function() { + return this.MongoManager.upsertIntoDocCollection + .calledWith(this.project_id, this.doc_id, { lines: this.newDocLines }) + .should.equal(true) + }) + + it('should not update the version', function() { + return this.MongoManager.setDocVersion.called.should.equal(false) + }) + + return it('should return the callback with the new rev', function() { + return this.callback + .calledWith(null, true, this.rev + 1) + .should.equal(true) + }) + }) + + describe('when the doc ranges have changed', function() { + beforeEach(function() { + this.DocManager._getDoc = sinon.stub().callsArgWith(3, null, this.doc) + this.RangeManager.shouldUpdateRanges.returns(true) + return this.DocManager.updateDoc( + this.project_id, + this.doc_id, + this.oldDocLines, + this.version, + this.newRanges, + this.callback + ) + }) + + it('should upsert the ranges', function() { + return this.MongoManager.upsertIntoDocCollection + .calledWith(this.project_id, this.doc_id, { ranges: this.newRanges }) + .should.equal(true) + }) + + it('should not update the version', function() { + return this.MongoManager.setDocVersion.called.should.equal(false) + }) + + return it('should return the callback with the new rev', function() { + return this.callback + .calledWith(null, true, this.rev + 1) + .should.equal(true) + }) + }) + + describe('when only the version has changed', function() { + beforeEach(function() { + this.DocManager._getDoc = sinon.stub().callsArgWith(3, null, this.doc) + return this.DocManager.updateDoc( + this.project_id, + this.doc_id, + this.oldDocLines, + this.version + 1, + this.originalRanges, + this.callback + ) + }) + + it('should not change the lines or ranges', function() { + return this.MongoManager.upsertIntoDocCollection.called.should.equal( + false + ) + }) + + it('should update the version', function() { + return this.MongoManager.setDocVersion + .calledWith(this.doc_id, this.version + 1) + .should.equal(true) + }) + + return it('should return the callback with the old rev', function() { + return this.callback.calledWith(null, true, this.rev).should.equal(true) + }) + }) + + describe('when the doc has not changed at all', function() { + beforeEach(function() { + this.DocManager._getDoc = sinon.stub().callsArgWith(3, null, this.doc) + return this.DocManager.updateDoc( + this.project_id, + this.doc_id, + this.oldDocLines, + this.version, + this.originalRanges, + this.callback + ) + }) + + it('should not update the ranges or lines', function() { + return this.MongoManager.upsertIntoDocCollection.called.should.equal( + false + ) + }) + + it('should not update the version', function() { + return this.MongoManager.setDocVersion.called.should.equal(false) + }) + + return it('should return the callback with the old rev and modified == false', function() { + return this.callback + .calledWith(null, false, this.rev) + .should.equal(true) + }) + }) + + describe('when the version is null', function() { + beforeEach(function() { + return this.DocManager.updateDoc( + this.project_id, + this.doc_id, + this.newDocLines, + null, + this.originalRanges, + this.callback + ) + }) + + return it('should return an error', function() { + return this.callback + .calledWith( + sinon.match.has('message', 'no lines, version or ranges provided') + ) + .should.equal(true) + }) + }) + + describe('when the lines are null', function() { + beforeEach(function() { + return this.DocManager.updateDoc( + this.project_id, + this.doc_id, + null, + this.version, + this.originalRanges, + this.callback + ) + }) + + return it('should return an error', function() { + return this.callback + .calledWith( + sinon.match.has('message', 'no lines, version or ranges provided') + ) + .should.equal(true) + }) + }) + + describe('when the ranges are null', function() { + beforeEach(function() { + return this.DocManager.updateDoc( + this.project_id, + this.doc_id, + this.newDocLines, + this.version, + null, + this.callback + ) + }) + + return it('should return an error', function() { + return this.callback + .calledWith( + sinon.match.has('message', 'no lines, version or ranges provided') + ) + .should.equal(true) + }) + }) + + describe('when there is a generic error getting the doc', function() { + beforeEach(function() { + this.error = new Error('doc could not be found') + this.DocManager._getDoc = sinon + .stub() + .callsArgWith(3, this.error, null, null) + return this.DocManager.updateDoc( + this.project_id, + this.doc_id, + this.newDocLines, + this.version, + this.originalRanges, + this.callback + ) + }) + + it('should not upsert the document to the doc collection', function() { + return this.MongoManager.upsertIntoDocCollection.called.should.equal( + false + ) + }) + + return it('should return the callback with the error', function() { + return this.callback.calledWith(this.error).should.equal(true) + }) + }) + + describe('when the doc lines have not changed', function() { + beforeEach(function() { + this.DocManager._getDoc = sinon.stub().callsArgWith(3, null, this.doc) + return this.DocManager.updateDoc( + this.project_id, + this.doc_id, + this.oldDocLines.slice(), + this.version, + this.originalRanges, + this.callback + ) + }) + + it('should not update the doc', function() { + return this.MongoManager.upsertIntoDocCollection.called.should.equal( + false + ) + }) + + return it('should return the callback with the existing rev', function() { + return this.callback + .calledWith(null, false, this.rev) + .should.equal(true) + }) + }) + + return describe('when the doc does not exist', function() { + beforeEach(function() { + this.DocManager._getDoc = sinon.stub().callsArgWith(3, null, null, null) + return this.DocManager.updateDoc( + this.project_id, + this.doc_id, + this.newDocLines, + this.version, + this.originalRanges, + this.callback + ) + }) + + it('should upsert the document to the doc collection', function() { + return this.MongoManager.upsertIntoDocCollection + .calledWith(this.project_id, this.doc_id, { + lines: this.newDocLines, + ranges: this.originalRanges + }) + .should.equal(true) + }) + + it('should set the version', function() { + return this.MongoManager.setDocVersion + .calledWith(this.doc_id, this.version) + .should.equal(true) + }) + + return it('should return the callback with the new rev', function() { + return this.callback.calledWith(null, true, 1).should.equal(true) + }) + }) + }) +}) diff --git a/services/docstore/test/unit/js/HttpControllerTests.js b/services/docstore/test/unit/js/HttpControllerTests.js index 27bb31a325..e282c247ff 100644 --- a/services/docstore/test/unit/js/HttpControllerTests.js +++ b/services/docstore/test/unit/js/HttpControllerTests.js @@ -9,442 +9,481 @@ * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const SandboxedModule = require('sandboxed-module'); -const { - assert -} = require("chai"); -const sinon = require('sinon'); -const chai = require('chai'); -chai.should(); -const { - expect -} = chai; -const modulePath = require('path').join(__dirname, '../../../app/js/HttpController'); -const { - ObjectId -} = require("mongojs"); +const SandboxedModule = require('sandboxed-module') +const { assert } = require('chai') +const sinon = require('sinon') +const chai = require('chai') +chai.should() +const { expect } = chai +const modulePath = require('path').join( + __dirname, + '../../../app/js/HttpController' +) +const { ObjectId } = require('mongojs') -describe("HttpController", function() { - beforeEach(function() { - this.HttpController = SandboxedModule.require(modulePath, { requires: { - "./DocManager": (this.DocManager = {}), - "./DocArchiveManager": (this.DocArchiveManager = {}), - "logger-sharelatex": (this.logger = { log: sinon.stub(), error: sinon.stub() }), - "./HealthChecker": {} - } - }); - this.res = { send: sinon.stub(), json: sinon.stub(), setHeader:sinon.stub() }; - this.res.status = sinon.stub().returns(this.res); - this.req = { query:{}}; - this.next = sinon.stub(); - this.project_id = "mock-project-id"; - this.doc_id = "mock-doc-id"; - this.doc = { - _id: this.doc_id, - lines: ["mock", "lines", " here", "", "", " spaces "], - version: 42, - rev: 5 - }; - return this.deletedDoc = { - deleted:true, - _id: this.doc_id, - lines: ["mock", "lines", " here", "", "", " spaces "], - version: 42, - rev: 5 - };}); +describe('HttpController', function() { + beforeEach(function() { + this.HttpController = SandboxedModule.require(modulePath, { + requires: { + './DocManager': (this.DocManager = {}), + './DocArchiveManager': (this.DocArchiveManager = {}), + 'logger-sharelatex': (this.logger = { + log: sinon.stub(), + error: sinon.stub() + }), + './HealthChecker': {} + } + }) + this.res = { + send: sinon.stub(), + json: sinon.stub(), + setHeader: sinon.stub() + } + this.res.status = sinon.stub().returns(this.res) + this.req = { query: {} } + this.next = sinon.stub() + this.project_id = 'mock-project-id' + this.doc_id = 'mock-doc-id' + this.doc = { + _id: this.doc_id, + lines: ['mock', 'lines', ' here', '', '', ' spaces '], + version: 42, + rev: 5 + } + return (this.deletedDoc = { + deleted: true, + _id: this.doc_id, + lines: ['mock', 'lines', ' here', '', '', ' spaces '], + version: 42, + rev: 5 + }) + }) - describe("getDoc", function() { + describe('getDoc', function() { + describe('without deleted docs', function() { + beforeEach(function() { + this.req.params = { + project_id: this.project_id, + doc_id: this.doc_id + } + this.DocManager.getFullDoc = sinon + .stub() + .callsArgWith(2, null, this.doc) + return this.HttpController.getDoc(this.req, this.res, this.next) + }) - describe("without deleted docs", function() { - beforeEach(function() { - this.req.params = { - project_id: this.project_id, - doc_id: this.doc_id - }; - this.DocManager.getFullDoc = sinon.stub().callsArgWith(2, null, this.doc); - return this.HttpController.getDoc(this.req, this.res, this.next); - }); + it('should get the document with the version (including deleted)', function() { + return this.DocManager.getFullDoc + .calledWith(this.project_id, this.doc_id) + .should.equal(true) + }) - it("should get the document with the version (including deleted)", function() { - return this.DocManager.getFullDoc - .calledWith(this.project_id, this.doc_id) - .should.equal(true); - }); + return it('should return the doc as JSON', function() { + return this.res.json + .calledWith({ + _id: this.doc_id, + lines: this.doc.lines, + rev: this.doc.rev, + version: this.doc.version + }) + .should.equal(true) + }) + }) - return it("should return the doc as JSON", function() { - return this.res.json - .calledWith({ - _id: this.doc_id, - lines: this.doc.lines, - rev: this.doc.rev, - version: this.doc.version - }) - .should.equal(true); - }); - }); + return describe('which is deleted', function() { + beforeEach(function() { + this.req.params = { + project_id: this.project_id, + doc_id: this.doc_id + } + return (this.DocManager.getFullDoc = sinon + .stub() + .callsArgWith(2, null, this.deletedDoc)) + }) - return describe("which is deleted", function() { - beforeEach(function() { - this.req.params = { - project_id: this.project_id, - doc_id: this.doc_id - }; - return this.DocManager.getFullDoc = sinon.stub().callsArgWith(2, null, this.deletedDoc); - }); + it('should get the doc from the doc manager', function() { + this.HttpController.getDoc(this.req, this.res, this.next) + return this.DocManager.getFullDoc + .calledWith(this.project_id, this.doc_id) + .should.equal(true) + }) - it("should get the doc from the doc manager", function() { - this.HttpController.getDoc(this.req, this.res, this.next); - return this.DocManager.getFullDoc.calledWith(this.project_id, this.doc_id).should.equal(true); - }); + it('should return 404 if the query string delete is not set ', function() { + this.HttpController.getDoc(this.req, this.res, this.next) + return this.res.send.calledWith(404).should.equal(true) + }) - it("should return 404 if the query string delete is not set ", function() { - this.HttpController.getDoc(this.req, this.res, this.next); - return this.res.send.calledWith(404).should.equal(true); - }); + return it('should return the doc as JSON if include_deleted is set to true', function() { + this.req.query.include_deleted = 'true' + this.HttpController.getDoc(this.req, this.res, this.next) + return this.res.json + .calledWith({ + _id: this.doc_id, + lines: this.doc.lines, + rev: this.doc.rev, + deleted: true, + version: this.doc.version + }) + .should.equal(true) + }) + }) + }) - return it("should return the doc as JSON if include_deleted is set to true", function() { - this.req.query.include_deleted = "true"; - this.HttpController.getDoc(this.req, this.res, this.next); - return this.res.json - .calledWith({ - _id: this.doc_id, - lines: this.doc.lines, - rev: this.doc.rev, - deleted: true, - version: this.doc.version - }) - .should.equal(true); - }); - }); - }); + describe('getRawDoc', function() { + beforeEach(function() { + this.req.params = { + project_id: this.project_id, + doc_id: this.doc_id + } + this.DocManager.getDocLines = sinon.stub().callsArgWith(2, null, this.doc) + return this.HttpController.getRawDoc(this.req, this.res, this.next) + }) - describe("getRawDoc", function() { - beforeEach(function() { - this.req.params = { - project_id: this.project_id, - doc_id: this.doc_id - }; - this.DocManager.getDocLines = sinon.stub().callsArgWith(2, null, this.doc); - return this.HttpController.getRawDoc(this.req, this.res, this.next); - }); + it('should get the document without the version', function() { + return this.DocManager.getDocLines + .calledWith(this.project_id, this.doc_id) + .should.equal(true) + }) - it("should get the document without the version", function() { - return this.DocManager.getDocLines - .calledWith(this.project_id, this.doc_id) - .should.equal(true); - }); + it('should set the content type header', function() { + return this.res.setHeader + .calledWith('content-type', 'text/plain') + .should.equal(true) + }) - it("should set the content type header", function() { - return this.res.setHeader.calledWith('content-type', 'text/plain').should.equal(true); - }); + return it('should send the raw version of the doc', function() { + return assert.deepEqual( + this.res.send.args[0][0], + `${this.doc.lines[0]}\n${this.doc.lines[1]}\n${this.doc.lines[2]}\n${this.doc.lines[3]}\n${this.doc.lines[4]}\n${this.doc.lines[5]}` + ) + }) + }) - return it("should send the raw version of the doc", function() { - return assert.deepEqual(this.res.send.args[0][0], `${this.doc.lines[0]}\n${this.doc.lines[1]}\n${this.doc.lines[2]}\n${this.doc.lines[3]}\n${this.doc.lines[4]}\n${this.doc.lines[5]}`); - }); - }); + describe('getAllDocs', function() { + describe('normally', function() { + beforeEach(function() { + this.req.params = { project_id: this.project_id } + this.docs = [ + { + _id: ObjectId(), + lines: ['mock', 'lines', 'one'], + rev: 2 + }, + { + _id: ObjectId(), + lines: ['mock', 'lines', 'two'], + rev: 4 + } + ] + this.DocManager.getAllNonDeletedDocs = sinon + .stub() + .callsArgWith(2, null, this.docs) + return this.HttpController.getAllDocs(this.req, this.res, this.next) + }) - describe("getAllDocs", function() { - describe("normally", function() { - beforeEach(function() { - this.req.params = - {project_id: this.project_id}; - this.docs = [{ - _id: ObjectId(), - lines: ["mock", "lines", "one"], - rev: 2 - }, { - _id: ObjectId(), - lines: ["mock", "lines", "two"], - rev: 4 - }]; - this.DocManager.getAllNonDeletedDocs = sinon.stub().callsArgWith(2, null, this.docs); - return this.HttpController.getAllDocs(this.req, this.res, this.next); - }); + it('should get all the (non-deleted) docs', function() { + return this.DocManager.getAllNonDeletedDocs + .calledWith(this.project_id, { lines: true, rev: true }) + .should.equal(true) + }) - it("should get all the (non-deleted) docs", function() { - return this.DocManager.getAllNonDeletedDocs - .calledWith(this.project_id, {lines: true, rev: true}) - .should.equal(true); - }); + return it('should return the doc as JSON', function() { + return this.res.json + .calledWith([ + { + _id: this.docs[0]._id.toString(), + lines: this.docs[0].lines, + rev: this.docs[0].rev + }, + { + _id: this.docs[1]._id.toString(), + lines: this.docs[1].lines, + rev: this.docs[1].rev + } + ]) + .should.equal(true) + }) + }) - return it("should return the doc as JSON", function() { - return this.res.json - .calledWith([{ - _id: this.docs[0]._id.toString(), - lines: this.docs[0].lines, - rev: this.docs[0].rev - }, { - _id: this.docs[1]._id.toString(), - lines: this.docs[1].lines, - rev: this.docs[1].rev - }]) - .should.equal(true); - }); - }); + return describe('with a null doc', function() { + beforeEach(function() { + this.req.params = { project_id: this.project_id } + this.docs = [ + { + _id: ObjectId(), + lines: ['mock', 'lines', 'one'], + rev: 2 + }, + null, + { + _id: ObjectId(), + lines: ['mock', 'lines', 'two'], + rev: 4 + } + ] + this.DocManager.getAllNonDeletedDocs = sinon + .stub() + .callsArgWith(2, null, this.docs) + return this.HttpController.getAllDocs(this.req, this.res, this.next) + }) - return describe("with a null doc", function() { - beforeEach(function() { - this.req.params = - {project_id: this.project_id}; - this.docs = [{ - _id: ObjectId(), - lines: ["mock", "lines", "one"], - rev: 2 - }, - null, - { - _id: ObjectId(), - lines: ["mock", "lines", "two"], - rev: 4 - }]; - this.DocManager.getAllNonDeletedDocs = sinon.stub().callsArgWith(2, null, this.docs); - return this.HttpController.getAllDocs(this.req, this.res, this.next); - }); + it('should return the non null docs as JSON', function() { + return this.res.json + .calledWith([ + { + _id: this.docs[0]._id.toString(), + lines: this.docs[0].lines, + rev: this.docs[0].rev + }, + { + _id: this.docs[2]._id.toString(), + lines: this.docs[2].lines, + rev: this.docs[2].rev + } + ]) + .should.equal(true) + }) - it("should return the non null docs as JSON", function() { - return this.res.json - .calledWith([{ - _id: this.docs[0]._id.toString(), - lines: this.docs[0].lines, - rev: this.docs[0].rev - }, { - _id: this.docs[2]._id.toString(), - lines: this.docs[2].lines, - rev: this.docs[2].rev - }]) - .should.equal(true); - }); + return it('should log out an error', function() { + return this.logger.error + .calledWith( + { + err: sinon.match.has('message', 'null doc'), + project_id: this.project_id + }, + 'encountered null doc' + ) + .should.equal(true) + }) + }) + }) - return it("should log out an error", function() { - return this.logger.error - .calledWith({ - err: sinon.match.has('message', "null doc"), - project_id: this.project_id - }, - "encountered null doc" - ) - .should.equal(true); - }); - }); - }); + describe('getAllRanges', function() { + return describe('normally', function() { + beforeEach(function() { + this.req.params = { project_id: this.project_id } + this.docs = [ + { + _id: ObjectId(), + ranges: { mock_ranges: 'one' } + }, + { + _id: ObjectId(), + ranges: { mock_ranges: 'two' } + } + ] + this.DocManager.getAllNonDeletedDocs = sinon + .stub() + .callsArgWith(2, null, this.docs) + return this.HttpController.getAllRanges(this.req, this.res, this.next) + }) - describe("getAllRanges", function() { return describe("normally", function() { - beforeEach(function() { - this.req.params = - {project_id: this.project_id}; - this.docs = [{ - _id: ObjectId(), - ranges: {"mock_ranges": "one"} - }, { - _id: ObjectId(), - ranges: {"mock_ranges": "two"} - }]; - this.DocManager.getAllNonDeletedDocs = sinon.stub().callsArgWith(2, null, this.docs); - return this.HttpController.getAllRanges(this.req, this.res, this.next); - }); + it('should get all the (non-deleted) doc ranges', function() { + return this.DocManager.getAllNonDeletedDocs + .calledWith(this.project_id, { ranges: true }) + .should.equal(true) + }) - it("should get all the (non-deleted) doc ranges", function() { - return this.DocManager.getAllNonDeletedDocs - .calledWith(this.project_id, {ranges: true}) - .should.equal(true); - }); + return it('should return the doc as JSON', function() { + return this.res.json + .calledWith([ + { + _id: this.docs[0]._id.toString(), + ranges: this.docs[0].ranges + }, + { + _id: this.docs[1]._id.toString(), + ranges: this.docs[1].ranges + } + ]) + .should.equal(true) + }) + }) + }) - return it("should return the doc as JSON", function() { - return this.res.json - .calledWith([{ - _id: this.docs[0]._id.toString(), - ranges: this.docs[0].ranges - }, { - _id: this.docs[1]._id.toString(), - ranges: this.docs[1].ranges - }]) - .should.equal(true); - }); - }); }); + describe('updateDoc', function() { + beforeEach(function() { + return (this.req.params = { + project_id: this.project_id, + doc_id: this.doc_id + }) + }) - describe("updateDoc", function() { - beforeEach(function() { - return this.req.params = { - project_id: this.project_id, - doc_id: this.doc_id - }; - }); + describe('when the doc lines exist and were updated', function() { + beforeEach(function() { + this.req.body = { + lines: (this.lines = ['hello', 'world']), + version: (this.version = 42), + ranges: (this.ranges = { changes: 'mock' }) + } + this.DocManager.updateDoc = sinon + .stub() + .yields(null, true, (this.rev = 5)) + return this.HttpController.updateDoc(this.req, this.res, this.next) + }) - describe("when the doc lines exist and were updated", function() { - beforeEach(function() { - this.req.body = { - lines: (this.lines = ["hello", "world"]), - version: (this.version = 42), - ranges: (this.ranges = { changes: "mock" }) - }; - this.DocManager.updateDoc = sinon.stub().yields(null, true, (this.rev = 5)); - return this.HttpController.updateDoc(this.req, this.res, this.next); - }); + it('should update the document', function() { + return this.DocManager.updateDoc + .calledWith( + this.project_id, + this.doc_id, + this.lines, + this.version, + this.ranges + ) + .should.equal(true) + }) - it("should update the document", function() { - return this.DocManager.updateDoc - .calledWith(this.project_id, this.doc_id, this.lines, this.version, this.ranges) - .should.equal(true); - }); + return it('should return a modified status', function() { + return this.res.json + .calledWith({ modified: true, rev: this.rev }) + .should.equal(true) + }) + }) - return it("should return a modified status", function() { - return this.res.json - .calledWith({modified: true, rev: this.rev}) - .should.equal(true); - }); - }); + describe('when the doc lines exist and were not updated', function() { + beforeEach(function() { + this.req.body = { + lines: (this.lines = ['hello', 'world']), + version: (this.version = 42), + ranges: {} + } + this.DocManager.updateDoc = sinon + .stub() + .yields(null, false, (this.rev = 5)) + return this.HttpController.updateDoc(this.req, this.res, this.next) + }) - describe("when the doc lines exist and were not updated", function() { - beforeEach(function() { - this.req.body = { - lines: (this.lines = ["hello", "world"]), - version: (this.version = 42), - ranges: {} - }; - this.DocManager.updateDoc = sinon.stub().yields(null, false, (this.rev = 5)); - return this.HttpController.updateDoc(this.req, this.res, this.next); - }); + return it('should return a modified status', function() { + return this.res.json + .calledWith({ modified: false, rev: this.rev }) + .should.equal(true) + }) + }) - return it("should return a modified status", function() { - return this.res.json - .calledWith({modified: false, rev: this.rev}) - .should.equal(true); - }); - }); + describe('when the doc lines are not provided', function() { + beforeEach(function() { + this.req.body = { version: 42, ranges: {} } + this.DocManager.updateDoc = sinon.stub().yields(null, false) + return this.HttpController.updateDoc(this.req, this.res, this.next) + }) - describe("when the doc lines are not provided", function() { - beforeEach(function() { - this.req.body = { version: 42, ranges: {} }; - this.DocManager.updateDoc = sinon.stub().yields(null, false); - return this.HttpController.updateDoc(this.req, this.res, this.next); - }); + it('should not update the document', function() { + return this.DocManager.updateDoc.called.should.equal(false) + }) - it("should not update the document", function() { - return this.DocManager.updateDoc.called.should.equal(false); - }); + return it('should return a 400 (bad request) response', function() { + return this.res.send.calledWith(400).should.equal(true) + }) + }) - return it("should return a 400 (bad request) response", function() { - return this.res.send - .calledWith(400) - .should.equal(true); - }); - }); + describe('when the doc version are not provided', function() { + beforeEach(function() { + this.req.body = { version: 42, lines: ['hello world'] } + this.DocManager.updateDoc = sinon.stub().yields(null, false) + return this.HttpController.updateDoc(this.req, this.res, this.next) + }) - describe("when the doc version are not provided", function() { - beforeEach(function() { - this.req.body = { version: 42, lines: ["hello world"] }; - this.DocManager.updateDoc = sinon.stub().yields(null, false); - return this.HttpController.updateDoc(this.req, this.res, this.next); - }); + it('should not update the document', function() { + return this.DocManager.updateDoc.called.should.equal(false) + }) - it("should not update the document", function() { - return this.DocManager.updateDoc.called.should.equal(false); - }); + return it('should return a 400 (bad request) response', function() { + return this.res.send.calledWith(400).should.equal(true) + }) + }) - return it("should return a 400 (bad request) response", function() { - return this.res.send - .calledWith(400) - .should.equal(true); - }); - }); + describe('when the doc ranges is not provided', function() { + beforeEach(function() { + this.req.body = { lines: ['foo'], version: 42 } + this.DocManager.updateDoc = sinon.stub().yields(null, false) + return this.HttpController.updateDoc(this.req, this.res, this.next) + }) - describe("when the doc ranges is not provided", function() { - beforeEach(function() { - this.req.body = { lines : [ "foo" ], version: 42 }; - this.DocManager.updateDoc = sinon.stub().yields(null, false); - return this.HttpController.updateDoc(this.req, this.res, this.next); - }); + it('should not update the document', function() { + return this.DocManager.updateDoc.called.should.equal(false) + }) - it("should not update the document", function() { - return this.DocManager.updateDoc.called.should.equal(false); - }); + return it('should return a 400 (bad request) response', function() { + return this.res.send.calledWith(400).should.equal(true) + }) + }) - return it("should return a 400 (bad request) response", function() { - return this.res.send - .calledWith(400) - .should.equal(true); - }); - }); + return describe('when the doc body is too large', function() { + beforeEach(function() { + this.req.body = { + lines: (this.lines = Array(2049).fill('a'.repeat(1024))), + version: (this.version = 42), + ranges: (this.ranges = { changes: 'mock' }) + } + return this.HttpController.updateDoc(this.req, this.res, this.next) + }) - return describe("when the doc body is too large", function() { - beforeEach(function() { - this.req.body = { - lines: (this.lines = Array(2049).fill('a'.repeat(1024))), - version: (this.version = 42), - ranges: (this.ranges = { changes: "mock" }) - }; - return this.HttpController.updateDoc(this.req, this.res, this.next); - }); + it('should return a 413 (too large) response', function() { + return sinon.assert.calledWith(this.res.status, 413) + }) - it("should return a 413 (too large) response", function() { - return sinon.assert.calledWith(this.res.status, 413); - }); + return it('should report that the document body is too large', function() { + return sinon.assert.calledWith(this.res.send, 'document body too large') + }) + }) + }) - return it("should report that the document body is too large", function() { - return sinon.assert.calledWith(this.res.send, "document body too large"); - }); - }); - }); + describe('deleteDoc', function() { + beforeEach(function() { + this.req.params = { + project_id: this.project_id, + doc_id: this.doc_id + } + this.DocManager.deleteDoc = sinon.stub().callsArg(2) + return this.HttpController.deleteDoc(this.req, this.res, this.next) + }) - describe("deleteDoc", function() { - beforeEach(function() { - this.req.params = { - project_id: this.project_id, - doc_id: this.doc_id - }; - this.DocManager.deleteDoc = sinon.stub().callsArg(2); - return this.HttpController.deleteDoc(this.req, this.res, this.next); - }); + it('should delete the document', function() { + return this.DocManager.deleteDoc + .calledWith(this.project_id, this.doc_id) + .should.equal(true) + }) - it("should delete the document", function() { - return this.DocManager.deleteDoc - .calledWith(this.project_id, this.doc_id) - .should.equal(true); - }); + return it('should return a 204 (No Content)', function() { + return this.res.send.calledWith(204).should.equal(true) + }) + }) - return it("should return a 204 (No Content)", function() { - return this.res.send - .calledWith(204) - .should.equal(true); - }); - }); + describe('archiveAllDocs', function() { + beforeEach(function() { + this.req.params = { project_id: this.project_id } + this.DocArchiveManager.archiveAllDocs = sinon.stub().callsArg(1) + return this.HttpController.archiveAllDocs(this.req, this.res, this.next) + }) - describe("archiveAllDocs", function() { - beforeEach(function() { - this.req.params = - {project_id: this.project_id}; - this.DocArchiveManager.archiveAllDocs = sinon.stub().callsArg(1); - return this.HttpController.archiveAllDocs(this.req, this.res, this.next); - }); + it('should archive the project', function() { + return this.DocArchiveManager.archiveAllDocs + .calledWith(this.project_id) + .should.equal(true) + }) - it("should archive the project", function() { - return this.DocArchiveManager.archiveAllDocs - .calledWith(this.project_id) - .should.equal(true); - }); + return it('should return a 204 (No Content)', function() { + return this.res.send.calledWith(204).should.equal(true) + }) + }) - return it("should return a 204 (No Content)", function() { - return this.res.send - .calledWith(204) - .should.equal(true); - }); - }); + return describe('destroyAllDocs', function() { + beforeEach(function() { + this.req.params = { project_id: this.project_id } + this.DocArchiveManager.destroyAllDocs = sinon.stub().callsArg(1) + return this.HttpController.destroyAllDocs(this.req, this.res, this.next) + }) - return describe("destroyAllDocs", function() { - beforeEach(function() { - this.req.params = - {project_id: this.project_id}; - this.DocArchiveManager.destroyAllDocs = sinon.stub().callsArg(1); - return this.HttpController.destroyAllDocs(this.req, this.res, this.next); - }); - - it("should destroy the docs", function() { - return sinon.assert.calledWith(this.DocArchiveManager.destroyAllDocs, this.project_id); - }); - - return it("should return 204", function() { - return sinon.assert.calledWith(this.res.send, 204); - }); - }); -}); + it('should destroy the docs', function() { + return sinon.assert.calledWith( + this.DocArchiveManager.destroyAllDocs, + this.project_id + ) + }) + return it('should return 204', function() { + return sinon.assert.calledWith(this.res.send, 204) + }) + }) +}) diff --git a/services/docstore/test/unit/js/MongoManagerTests.js b/services/docstore/test/unit/js/MongoManagerTests.js index d7dabe3afb..0af25c5ce7 100644 --- a/services/docstore/test/unit/js/MongoManagerTests.js +++ b/services/docstore/test/unit/js/MongoManagerTests.js @@ -9,223 +9,285 @@ * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const SandboxedModule = require('sandboxed-module'); -const sinon = require('sinon'); -require('chai').should(); -const modulePath = require('path').join(__dirname, '../../../app/js/MongoManager'); -const { - ObjectId -} = require("mongojs"); -const { - assert -} = require("chai"); +const SandboxedModule = require('sandboxed-module') +const sinon = require('sinon') +require('chai').should() +const modulePath = require('path').join( + __dirname, + '../../../app/js/MongoManager' +) +const { ObjectId } = require('mongojs') +const { assert } = require('chai') -describe("MongoManager", function() { - beforeEach(function() { - this.MongoManager = SandboxedModule.require(modulePath, { requires: { - "./mongojs": { - db: (this.db = { docs: {}, docOps: {} }), - ObjectId - }, - 'metrics-sharelatex': {timeAsyncMethod: sinon.stub()}, - 'logger-sharelatex': {log(){}} - } - }); - this.project_id = ObjectId().toString(); - this.doc_id = ObjectId().toString(); - this.callback = sinon.stub(); - return this.stubbedErr = new Error("hello world"); - }); +describe('MongoManager', function() { + beforeEach(function() { + this.MongoManager = SandboxedModule.require(modulePath, { + requires: { + './mongojs': { + db: (this.db = { docs: {}, docOps: {} }), + ObjectId + }, + 'metrics-sharelatex': { timeAsyncMethod: sinon.stub() }, + 'logger-sharelatex': { log() {} } + } + }) + this.project_id = ObjectId().toString() + this.doc_id = ObjectId().toString() + this.callback = sinon.stub() + return (this.stubbedErr = new Error('hello world')) + }) - describe("findDoc", function() { - beforeEach(function() { - this.doc = { name: "mock-doc"}; - this.db.docs.find = sinon.stub().callsArgWith(2, null, [this.doc]); - this.filter = { lines: true }; - return this.MongoManager.findDoc(this.project_id, this.doc_id, this.filter, this.callback); - }); + describe('findDoc', function() { + beforeEach(function() { + this.doc = { name: 'mock-doc' } + this.db.docs.find = sinon.stub().callsArgWith(2, null, [this.doc]) + this.filter = { lines: true } + return this.MongoManager.findDoc( + this.project_id, + this.doc_id, + this.filter, + this.callback + ) + }) - it("should find the doc", function() { - return this.db.docs.find - .calledWith({ - _id: ObjectId(this.doc_id), - project_id: ObjectId(this.project_id) - }, this.filter) - .should.equal(true); - }); + it('should find the doc', function() { + return this.db.docs.find + .calledWith( + { + _id: ObjectId(this.doc_id), + project_id: ObjectId(this.project_id) + }, + this.filter + ) + .should.equal(true) + }) - return it("should call the callback with the doc", function() { - return this.callback.calledWith(null, this.doc).should.equal(true); - }); - }); + return it('should call the callback with the doc', function() { + return this.callback.calledWith(null, this.doc).should.equal(true) + }) + }) - describe("getProjectsDocs", function() { - beforeEach(function() { - this.filter = {lines: true}; - this.doc1 = { name: "mock-doc1" }; - this.doc2 = { name: "mock-doc2" }; - this.doc3 = { name: "mock-doc3" }; - this.doc4 = { name: "mock-doc4" }; - return this.db.docs.find = sinon.stub().callsArgWith(2, null, [this.doc, this.doc3, this.doc4]); - }); - - describe("with included_deleted = false", function() { - beforeEach(function() { - return this.MongoManager.getProjectsDocs(this.project_id, {include_deleted: false}, this.filter, this.callback); - }); + describe('getProjectsDocs', function() { + beforeEach(function() { + this.filter = { lines: true } + this.doc1 = { name: 'mock-doc1' } + this.doc2 = { name: 'mock-doc2' } + this.doc3 = { name: 'mock-doc3' } + this.doc4 = { name: 'mock-doc4' } + return (this.db.docs.find = sinon + .stub() + .callsArgWith(2, null, [this.doc, this.doc3, this.doc4])) + }) - it("should find the non-deleted docs via the project_id", function() { - return this.db.docs.find - .calledWith({ - project_id: ObjectId(this.project_id), - deleted: { $ne: true } - }, this.filter) - .should.equal(true); - }); + describe('with included_deleted = false', function() { + beforeEach(function() { + return this.MongoManager.getProjectsDocs( + this.project_id, + { include_deleted: false }, + this.filter, + this.callback + ) + }) - return it("should call the callback with the docs", function() { - return this.callback.calledWith(null, [this.doc, this.doc3, this.doc4]).should.equal(true); - }); - }); - - return describe("with included_deleted = true", function() { - beforeEach(function() { - return this.MongoManager.getProjectsDocs(this.project_id, {include_deleted: true}, this.filter, this.callback); - }); + it('should find the non-deleted docs via the project_id', function() { + return this.db.docs.find + .calledWith( + { + project_id: ObjectId(this.project_id), + deleted: { $ne: true } + }, + this.filter + ) + .should.equal(true) + }) - it("should find all via the project_id", function() { - return this.db.docs.find - .calledWith({ - project_id: ObjectId(this.project_id) - }, this.filter) - .should.equal(true); - }); + return it('should call the callback with the docs', function() { + return this.callback + .calledWith(null, [this.doc, this.doc3, this.doc4]) + .should.equal(true) + }) + }) - return it("should call the callback with the docs", function() { - return this.callback.calledWith(null, [this.doc, this.doc3, this.doc4]).should.equal(true); - }); - }); - }); + return describe('with included_deleted = true', function() { + beforeEach(function() { + return this.MongoManager.getProjectsDocs( + this.project_id, + { include_deleted: true }, + this.filter, + this.callback + ) + }) - describe("upsertIntoDocCollection", function() { - beforeEach(function() { - this.db.docs.update = sinon.stub().callsArgWith(3, this.stubbedErr); - return this.oldRev = 77; - }); + it('should find all via the project_id', function() { + return this.db.docs.find + .calledWith( + { + project_id: ObjectId(this.project_id) + }, + this.filter + ) + .should.equal(true) + }) - it("should upsert the document", function(done){ - return this.MongoManager.upsertIntoDocCollection(this.project_id, this.doc_id, {lines: this.lines}, err=> { - const args = this.db.docs.update.args[0]; - assert.deepEqual(args[0], {_id: ObjectId(this.doc_id)}); - assert.equal(args[1].$set.lines, this.lines); - assert.equal(args[1].$inc.rev, 1); - assert.deepEqual(args[1].$set.project_id, ObjectId(this.project_id)); - return done(); - }); - }); + return it('should call the callback with the docs', function() { + return this.callback + .calledWith(null, [this.doc, this.doc3, this.doc4]) + .should.equal(true) + }) + }) + }) - return it("should return the error", function(done){ - return this.MongoManager.upsertIntoDocCollection(this.project_id, this.doc_id, {lines: this.lines}, err=> { - err.should.equal(this.stubbedErr); - return done(); - }); - }); - }); + describe('upsertIntoDocCollection', function() { + beforeEach(function() { + this.db.docs.update = sinon.stub().callsArgWith(3, this.stubbedErr) + return (this.oldRev = 77) + }) - describe("markDocAsDeleted", function() { - beforeEach(function() { - this.db.docs.update = sinon.stub().callsArgWith(2, this.stubbedErr); - return this.oldRev = 77; - }); + it('should upsert the document', function(done) { + return this.MongoManager.upsertIntoDocCollection( + this.project_id, + this.doc_id, + { lines: this.lines }, + err => { + const args = this.db.docs.update.args[0] + assert.deepEqual(args[0], { _id: ObjectId(this.doc_id) }) + assert.equal(args[1].$set.lines, this.lines) + assert.equal(args[1].$inc.rev, 1) + assert.deepEqual(args[1].$set.project_id, ObjectId(this.project_id)) + return done() + } + ) + }) - it("should process the update", function(done) { - return this.MongoManager.markDocAsDeleted(this.project_id, this.doc_id, err=> { - const args = this.db.docs.update.args[0]; - assert.deepEqual(args[0], {_id: ObjectId(this.doc_id), project_id: ObjectId(this.project_id)}); - assert.equal(args[1].$set.deleted, true); - return done(); - }); - }); + return it('should return the error', function(done) { + return this.MongoManager.upsertIntoDocCollection( + this.project_id, + this.doc_id, + { lines: this.lines }, + err => { + err.should.equal(this.stubbedErr) + return done() + } + ) + }) + }) - return it("should return the error", function(done){ - return this.MongoManager.markDocAsDeleted(this.project_id, this.doc_id, err=> { - err.should.equal(this.stubbedErr); - return done(); - }); - }); - }); + describe('markDocAsDeleted', function() { + beforeEach(function() { + this.db.docs.update = sinon.stub().callsArgWith(2, this.stubbedErr) + return (this.oldRev = 77) + }) - describe("destroyDoc", function() { - beforeEach(function(done) { - this.db.docs.remove = sinon.stub().yields(); - this.db.docOps.remove = sinon.stub().yields(); - return this.MongoManager.destroyDoc('123456789012', done); - }); + it('should process the update', function(done) { + return this.MongoManager.markDocAsDeleted( + this.project_id, + this.doc_id, + err => { + const args = this.db.docs.update.args[0] + assert.deepEqual(args[0], { + _id: ObjectId(this.doc_id), + project_id: ObjectId(this.project_id) + }) + assert.equal(args[1].$set.deleted, true) + return done() + } + ) + }) - it("should destroy the doc", function() { - return sinon.assert.calledWith(this.db.docs.remove, {_id: ObjectId('123456789012')}); - }); + return it('should return the error', function(done) { + return this.MongoManager.markDocAsDeleted( + this.project_id, + this.doc_id, + err => { + err.should.equal(this.stubbedErr) + return done() + } + ) + }) + }) - return it("should destroy the docOps", function() { - return sinon.assert.calledWith(this.db.docOps.remove, {doc_id: ObjectId('123456789012')}); - }); - }); + describe('destroyDoc', function() { + beforeEach(function(done) { + this.db.docs.remove = sinon.stub().yields() + this.db.docOps.remove = sinon.stub().yields() + return this.MongoManager.destroyDoc('123456789012', done) + }) - describe("getDocVersion", function() { - describe("when the doc exists", function() { - beforeEach(function() { - this.doc = - {version: (this.version = 42)}; - this.db.docOps.find = sinon.stub().callsArgWith(2, null, [this.doc]); - return this.MongoManager.getDocVersion(this.doc_id, this.callback); - }); + it('should destroy the doc', function() { + return sinon.assert.calledWith(this.db.docs.remove, { + _id: ObjectId('123456789012') + }) + }) - it("should look for the doc in the database", function() { - return this.db.docOps.find - .calledWith({ doc_id: ObjectId(this.doc_id) }, {version: 1}) - .should.equal(true); - }); + return it('should destroy the docOps', function() { + return sinon.assert.calledWith(this.db.docOps.remove, { + doc_id: ObjectId('123456789012') + }) + }) + }) - return it("should call the callback with the version", function() { - return this.callback.calledWith(null, this.version).should.equal(true); - }); - }); + describe('getDocVersion', function() { + describe('when the doc exists', function() { + beforeEach(function() { + this.doc = { version: (this.version = 42) } + this.db.docOps.find = sinon.stub().callsArgWith(2, null, [this.doc]) + return this.MongoManager.getDocVersion(this.doc_id, this.callback) + }) - return describe("when the doc doesn't exist", function() { - beforeEach(function() { - this.db.docOps.find = sinon.stub().callsArgWith(2, null, []); - return this.MongoManager.getDocVersion(this.doc_id, this.callback); - }); + it('should look for the doc in the database', function() { + return this.db.docOps.find + .calledWith({ doc_id: ObjectId(this.doc_id) }, { version: 1 }) + .should.equal(true) + }) - return it("should call the callback with 0", function() { - return this.callback.calledWith(null, 0).should.equal(true); - }); - }); - }); + return it('should call the callback with the version', function() { + return this.callback.calledWith(null, this.version).should.equal(true) + }) + }) - return describe("setDocVersion", function() { - beforeEach(function() { - this.version = 42; - this.db.docOps.update = sinon.stub().callsArg(3); - return this.MongoManager.setDocVersion(this.doc_id, this.version, this.callback); - }); + return describe("when the doc doesn't exist", function() { + beforeEach(function() { + this.db.docOps.find = sinon.stub().callsArgWith(2, null, []) + return this.MongoManager.getDocVersion(this.doc_id, this.callback) + }) - it("should update the doc version", function() { - return this.db.docOps.update - .calledWith({ - doc_id: ObjectId(this.doc_id) - }, { - $set: { - version: this.version - } - }, { - upsert: true - }) - .should.equal(true); - }); + return it('should call the callback with 0', function() { + return this.callback.calledWith(null, 0).should.equal(true) + }) + }) + }) - return it("should call the callback", function() { - return this.callback.called.should.equal(true); - }); - }); -}); + return describe('setDocVersion', function() { + beforeEach(function() { + this.version = 42 + this.db.docOps.update = sinon.stub().callsArg(3) + return this.MongoManager.setDocVersion( + this.doc_id, + this.version, + this.callback + ) + }) + + it('should update the doc version', function() { + return this.db.docOps.update + .calledWith( + { + doc_id: ObjectId(this.doc_id) + }, + { + $set: { + version: this.version + } + }, + { + upsert: true + } + ) + .should.equal(true) + }) + + return it('should call the callback', function() { + return this.callback.called.should.equal(true) + }) + }) +}) diff --git a/services/docstore/test/unit/js/RangeManagerTests.js b/services/docstore/test/unit/js/RangeManagerTests.js index b67e535181..ff6d96a0d1 100644 --- a/services/docstore/test/unit/js/RangeManagerTests.js +++ b/services/docstore/test/unit/js/RangeManagerTests.js @@ -10,190 +10,248 @@ * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const SandboxedModule = require('sandboxed-module'); -const sinon = require('sinon'); -require('chai').should(); -const { - expect -} = require('chai'); -const modulePath = require('path').join(__dirname, '../../../app/js/RangeManager'); -const { - ObjectId -} = require("mongojs"); -const { - assert -} = require("chai"); -const _ = require("underscore"); +const SandboxedModule = require('sandboxed-module') +const sinon = require('sinon') +require('chai').should() +const { expect } = require('chai') +const modulePath = require('path').join( + __dirname, + '../../../app/js/RangeManager' +) +const { ObjectId } = require('mongojs') +const { assert } = require('chai') +const _ = require('underscore') -describe("RangeManager", function() { - beforeEach(function() { - return this.RangeManager = SandboxedModule.require(modulePath, { requires: { - "./mongojs": { - ObjectId - } - } - } - ); - }); +describe('RangeManager', function() { + beforeEach(function() { + return (this.RangeManager = SandboxedModule.require(modulePath, { + requires: { + './mongojs': { + ObjectId + } + } + })) + }) - describe("jsonRangesToMongo", function() { - it("should convert ObjectIds and dates to proper objects", function() { - const change_id = ObjectId().toString(); - const comment_id = ObjectId().toString(); - const user_id = ObjectId().toString(); - const thread_id = ObjectId().toString(); - const ts = new Date().toJSON(); - return this.RangeManager.jsonRangesToMongo({ - changes: [{ - id: change_id, - op: { i: "foo", p: 3 }, - metadata: { - user_id, - ts - } - }], - comments: [{ - id: comment_id, - op: { c: "foo", p: 3, t: thread_id } - }] - }).should.deep.equal({ - changes: [{ - id: ObjectId(change_id), - op: { i: "foo", p: 3 }, - metadata: { - user_id: ObjectId(user_id), - ts: new Date(ts) - } - }], - comments: [{ - id: ObjectId(comment_id), - op: { c: "foo", p: 3, t: ObjectId(thread_id) } - }] - }); - }); - - it("should leave malformed ObjectIds as they are", function() { - const change_id = "foo"; - const comment_id = "bar"; - const user_id = "baz"; - return this.RangeManager.jsonRangesToMongo({ - changes: [{ - id: change_id, - metadata: { - user_id - } - }], - comments: [{ - id: comment_id - }] - }).should.deep.equal({ - changes: [{ - id: change_id, - metadata: { - user_id - } - }], - comments: [{ - id: comment_id - }] - }); - }); - - return it("should be consistent when transformed through json -> mongo -> json", function() { - const change_id = ObjectId().toString(); - const comment_id = ObjectId().toString(); - const user_id = ObjectId().toString(); - const thread_id = ObjectId().toString(); - const ts = new Date().toJSON(); - const ranges1 = { - changes: [{ - id: change_id, - op: { i: "foo", p: 3 }, - metadata: { - user_id, - ts - } - }], - comments: [{ - id: comment_id, - op: { c: "foo", p: 3, t: thread_id } - }] - }; - const ranges1_copy = JSON.parse(JSON.stringify(ranges1)); // jsonRangesToMongo modifies in place - const ranges2 = JSON.parse(JSON.stringify(this.RangeManager.jsonRangesToMongo(ranges1_copy))); - return ranges1.should.deep.equal(ranges2); - }); - }); - - return describe("shouldUpdateRanges", function() { - beforeEach(function() { - this.ranges = { - changes: [{ - id: ObjectId(), - op: { i: "foo", p: 3 }, - metadata: { - user_id: ObjectId(), - ts: new Date() - } - }], - comments: [{ - id: ObjectId(), - op: { c: "foo", p: 3, t: ObjectId() } - }] - }; - return this.ranges_copy = this.RangeManager.jsonRangesToMongo(JSON.parse(JSON.stringify(this.ranges))); - }); + describe('jsonRangesToMongo', function() { + it('should convert ObjectIds and dates to proper objects', function() { + const change_id = ObjectId().toString() + const comment_id = ObjectId().toString() + const user_id = ObjectId().toString() + const thread_id = ObjectId().toString() + const ts = new Date().toJSON() + return this.RangeManager.jsonRangesToMongo({ + changes: [ + { + id: change_id, + op: { i: 'foo', p: 3 }, + metadata: { + user_id, + ts + } + } + ], + comments: [ + { + id: comment_id, + op: { c: 'foo', p: 3, t: thread_id } + } + ] + }).should.deep.equal({ + changes: [ + { + id: ObjectId(change_id), + op: { i: 'foo', p: 3 }, + metadata: { + user_id: ObjectId(user_id), + ts: new Date(ts) + } + } + ], + comments: [ + { + id: ObjectId(comment_id), + op: { c: 'foo', p: 3, t: ObjectId(thread_id) } + } + ] + }) + }) - describe("with a blank new range", function() { return it("should throw an error", function() { - return expect(() => { - return this.RangeManager.shouldUpdateRanges(this.ranges, null); - }).to.throw(Error); - }); }); - - describe("with a blank old range", function() { return it("should treat it like {}", function() { - this.RangeManager.shouldUpdateRanges(null, {}).should.equal(false); - return this.RangeManager.shouldUpdateRanges(null, this.ranges).should.equal(true); - }); }); - - describe("with no changes", function() { return it("should return false", function() { - return this.RangeManager.shouldUpdateRanges(this.ranges, this.ranges_copy).should.equal(false); - }); }); - - return describe("with changes", function() { - it("should return true when the change id changes", function() { - this.ranges_copy.changes[0].id = ObjectId(); - return this.RangeManager.shouldUpdateRanges(this.ranges, this.ranges_copy).should.equal(true); - }); + it('should leave malformed ObjectIds as they are', function() { + const change_id = 'foo' + const comment_id = 'bar' + const user_id = 'baz' + return this.RangeManager.jsonRangesToMongo({ + changes: [ + { + id: change_id, + metadata: { + user_id + } + } + ], + comments: [ + { + id: comment_id + } + ] + }).should.deep.equal({ + changes: [ + { + id: change_id, + metadata: { + user_id + } + } + ], + comments: [ + { + id: comment_id + } + ] + }) + }) - it("should return true when the change user id changes", function() { - this.ranges_copy.changes[0].metadata.user_id = ObjectId(); - return this.RangeManager.shouldUpdateRanges(this.ranges, this.ranges_copy).should.equal(true); - }); + return it('should be consistent when transformed through json -> mongo -> json', function() { + const change_id = ObjectId().toString() + const comment_id = ObjectId().toString() + const user_id = ObjectId().toString() + const thread_id = ObjectId().toString() + const ts = new Date().toJSON() + const ranges1 = { + changes: [ + { + id: change_id, + op: { i: 'foo', p: 3 }, + metadata: { + user_id, + ts + } + } + ], + comments: [ + { + id: comment_id, + op: { c: 'foo', p: 3, t: thread_id } + } + ] + } + const ranges1_copy = JSON.parse(JSON.stringify(ranges1)) // jsonRangesToMongo modifies in place + const ranges2 = JSON.parse( + JSON.stringify(this.RangeManager.jsonRangesToMongo(ranges1_copy)) + ) + return ranges1.should.deep.equal(ranges2) + }) + }) - it("should return true when the change ts changes", function() { - this.ranges_copy.changes[0].metadata.ts = new Date(Date.now() + 1000); - return this.RangeManager.shouldUpdateRanges(this.ranges, this.ranges_copy).should.equal(true); - }); + return describe('shouldUpdateRanges', function() { + beforeEach(function() { + this.ranges = { + changes: [ + { + id: ObjectId(), + op: { i: 'foo', p: 3 }, + metadata: { + user_id: ObjectId(), + ts: new Date() + } + } + ], + comments: [ + { + id: ObjectId(), + op: { c: 'foo', p: 3, t: ObjectId() } + } + ] + } + return (this.ranges_copy = this.RangeManager.jsonRangesToMongo( + JSON.parse(JSON.stringify(this.ranges)) + )) + }) - it("should return true when the change op changes", function() { - this.ranges_copy.changes[0].op.i = "bar"; - return this.RangeManager.shouldUpdateRanges(this.ranges, this.ranges_copy).should.equal(true); - }); + describe('with a blank new range', function() { + return it('should throw an error', function() { + return expect(() => { + return this.RangeManager.shouldUpdateRanges(this.ranges, null) + }).to.throw(Error) + }) + }) - it("should return true when the comment id changes", function() { - this.ranges_copy.comments[0].id = ObjectId(); - return this.RangeManager.shouldUpdateRanges(this.ranges, this.ranges_copy).should.equal(true); - }); + describe('with a blank old range', function() { + return it('should treat it like {}', function() { + this.RangeManager.shouldUpdateRanges(null, {}).should.equal(false) + return this.RangeManager.shouldUpdateRanges( + null, + this.ranges + ).should.equal(true) + }) + }) - it("should return true when the comment offset changes", function() { - this.ranges_copy.comments[0].op.p = 17; - return this.RangeManager.shouldUpdateRanges(this.ranges, this.ranges_copy).should.equal(true); - }); + describe('with no changes', function() { + return it('should return false', function() { + return this.RangeManager.shouldUpdateRanges( + this.ranges, + this.ranges_copy + ).should.equal(false) + }) + }) - return it("should return true when the comment content changes", function() { - this.ranges_copy.comments[0].op.c = "bar"; - return this.RangeManager.shouldUpdateRanges(this.ranges, this.ranges_copy).should.equal(true); - }); - }); - }); -}); \ No newline at end of file + return describe('with changes', function() { + it('should return true when the change id changes', function() { + this.ranges_copy.changes[0].id = ObjectId() + return this.RangeManager.shouldUpdateRanges( + this.ranges, + this.ranges_copy + ).should.equal(true) + }) + + it('should return true when the change user id changes', function() { + this.ranges_copy.changes[0].metadata.user_id = ObjectId() + return this.RangeManager.shouldUpdateRanges( + this.ranges, + this.ranges_copy + ).should.equal(true) + }) + + it('should return true when the change ts changes', function() { + this.ranges_copy.changes[0].metadata.ts = new Date(Date.now() + 1000) + return this.RangeManager.shouldUpdateRanges( + this.ranges, + this.ranges_copy + ).should.equal(true) + }) + + it('should return true when the change op changes', function() { + this.ranges_copy.changes[0].op.i = 'bar' + return this.RangeManager.shouldUpdateRanges( + this.ranges, + this.ranges_copy + ).should.equal(true) + }) + + it('should return true when the comment id changes', function() { + this.ranges_copy.comments[0].id = ObjectId() + return this.RangeManager.shouldUpdateRanges( + this.ranges, + this.ranges_copy + ).should.equal(true) + }) + + it('should return true when the comment offset changes', function() { + this.ranges_copy.comments[0].op.p = 17 + return this.RangeManager.shouldUpdateRanges( + this.ranges, + this.ranges_copy + ).should.equal(true) + }) + + return it('should return true when the comment content changes', function() { + this.ranges_copy.comments[0].op.c = 'bar' + return this.RangeManager.shouldUpdateRanges( + this.ranges, + this.ranges_copy + ).should.equal(true) + }) + }) + }) +}) From 93c718dae9985266ee234a75b5e0aa23778fd647 Mon Sep 17 00:00:00 2001 From: decaffeinate Date: Sun, 16 Feb 2020 14:03:00 +0000 Subject: [PATCH 14/27] decaffeinate: Rename ArchiveDocsTests.coffee and 6 other files from .coffee to .js --- .../coffee/{ArchiveDocsTests.coffee => ArchiveDocsTests.js} | 0 .../coffee/{DeletingDocsTests.coffee => DeletingDocsTests.js} | 0 .../coffee/{GettingAllDocsTests.coffee => GettingAllDocsTests.js} | 0 .../coffee/{GettingDocsTests.coffee => GettingDocsTests.js} | 0 .../coffee/{UpdatingDocsTests.coffee => UpdatingDocsTests.js} | 0 .../coffee/helpers/{DocstoreApp.coffee => DocstoreApp.js} | 0 .../coffee/helpers/{DocstoreClient.coffee => DocstoreClient.js} | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename services/docstore/test/acceptance/coffee/{ArchiveDocsTests.coffee => ArchiveDocsTests.js} (100%) rename services/docstore/test/acceptance/coffee/{DeletingDocsTests.coffee => DeletingDocsTests.js} (100%) rename services/docstore/test/acceptance/coffee/{GettingAllDocsTests.coffee => GettingAllDocsTests.js} (100%) rename services/docstore/test/acceptance/coffee/{GettingDocsTests.coffee => GettingDocsTests.js} (100%) rename services/docstore/test/acceptance/coffee/{UpdatingDocsTests.coffee => UpdatingDocsTests.js} (100%) rename services/docstore/test/acceptance/coffee/helpers/{DocstoreApp.coffee => DocstoreApp.js} (100%) rename services/docstore/test/acceptance/coffee/helpers/{DocstoreClient.coffee => DocstoreClient.js} (100%) diff --git a/services/docstore/test/acceptance/coffee/ArchiveDocsTests.coffee b/services/docstore/test/acceptance/coffee/ArchiveDocsTests.js similarity index 100% rename from services/docstore/test/acceptance/coffee/ArchiveDocsTests.coffee rename to services/docstore/test/acceptance/coffee/ArchiveDocsTests.js diff --git a/services/docstore/test/acceptance/coffee/DeletingDocsTests.coffee b/services/docstore/test/acceptance/coffee/DeletingDocsTests.js similarity index 100% rename from services/docstore/test/acceptance/coffee/DeletingDocsTests.coffee rename to services/docstore/test/acceptance/coffee/DeletingDocsTests.js diff --git a/services/docstore/test/acceptance/coffee/GettingAllDocsTests.coffee b/services/docstore/test/acceptance/coffee/GettingAllDocsTests.js similarity index 100% rename from services/docstore/test/acceptance/coffee/GettingAllDocsTests.coffee rename to services/docstore/test/acceptance/coffee/GettingAllDocsTests.js diff --git a/services/docstore/test/acceptance/coffee/GettingDocsTests.coffee b/services/docstore/test/acceptance/coffee/GettingDocsTests.js similarity index 100% rename from services/docstore/test/acceptance/coffee/GettingDocsTests.coffee rename to services/docstore/test/acceptance/coffee/GettingDocsTests.js diff --git a/services/docstore/test/acceptance/coffee/UpdatingDocsTests.coffee b/services/docstore/test/acceptance/coffee/UpdatingDocsTests.js similarity index 100% rename from services/docstore/test/acceptance/coffee/UpdatingDocsTests.coffee rename to services/docstore/test/acceptance/coffee/UpdatingDocsTests.js diff --git a/services/docstore/test/acceptance/coffee/helpers/DocstoreApp.coffee b/services/docstore/test/acceptance/coffee/helpers/DocstoreApp.js similarity index 100% rename from services/docstore/test/acceptance/coffee/helpers/DocstoreApp.coffee rename to services/docstore/test/acceptance/coffee/helpers/DocstoreApp.js diff --git a/services/docstore/test/acceptance/coffee/helpers/DocstoreClient.coffee b/services/docstore/test/acceptance/coffee/helpers/DocstoreClient.js similarity index 100% rename from services/docstore/test/acceptance/coffee/helpers/DocstoreClient.coffee rename to services/docstore/test/acceptance/coffee/helpers/DocstoreClient.js From 73b0bc023f6b5f2fd616bb4b3f874bda419a3a4a Mon Sep 17 00:00:00 2001 From: decaffeinate Date: Sun, 16 Feb 2020 14:03:02 +0000 Subject: [PATCH 15/27] decaffeinate: Convert ArchiveDocsTests.coffee and 6 other files to JS --- .../acceptance/coffee/ArchiveDocsTests.js | 774 ++++++++++-------- .../acceptance/coffee/DeletingDocsTests.js | 181 ++-- .../acceptance/coffee/GettingAllDocsTests.js | 122 +-- .../acceptance/coffee/GettingDocsTests.js | 124 +-- .../acceptance/coffee/UpdatingDocsTests.js | 463 +++++++---- .../acceptance/coffee/helpers/DocstoreApp.js | 58 +- .../coffee/helpers/DocstoreClient.js | 119 +-- 7 files changed, 1098 insertions(+), 743 deletions(-) diff --git a/services/docstore/test/acceptance/coffee/ArchiveDocsTests.js b/services/docstore/test/acceptance/coffee/ArchiveDocsTests.js index 0291eef032..ac3a14f637 100644 --- a/services/docstore/test/acceptance/coffee/ArchiveDocsTests.js +++ b/services/docstore/test/acceptance/coffee/ArchiveDocsTests.js @@ -1,392 +1,518 @@ -sinon = require "sinon" -chai = require("chai") -should = chai.should() -{db, ObjectId, ISODate} = require "../../../app/js/mongojs" -async = require "async" -Settings = require("settings-sharelatex") -DocArchiveManager = require("../../../app/js/DocArchiveManager.js") -request = require "request" -DocstoreApp = require "./helpers/DocstoreApp" -DocstoreClient = require "./helpers/DocstoreClient" +/* + * decaffeinate suggestions: + * DS101: Remove unnecessary use of Array.from + * DS102: Remove unnecessary code created because of implicit returns + * DS207: Consider shorter variations of null checks + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +const sinon = require("sinon"); +const chai = require("chai"); +const should = chai.should(); +const {db, ObjectId, ISODate} = require("../../../app/js/mongojs"); +const async = require("async"); +const Settings = require("settings-sharelatex"); +const DocArchiveManager = require("../../../app/js/DocArchiveManager.js"); +const request = require("request"); +const DocstoreApp = require("./helpers/DocstoreApp"); +const DocstoreClient = require("./helpers/DocstoreClient"); -describe "Archiving", -> +describe("Archiving", function() { - before (done)-> - DocstoreApp.ensureRunning(done) + before(done => DocstoreApp.ensureRunning(done)); - describe "multiple docs in a project", -> - before (done) -> - @project_id = ObjectId() - @docs = [{ - _id: ObjectId() - lines: ["one", "two", "three"] - ranges: {} + describe("multiple docs in a project", function() { + before(function(done) { + this.project_id = ObjectId(); + this.docs = [{ + _id: ObjectId(), + lines: ["one", "two", "three"], + ranges: {}, version: 2 }, { - _id: ObjectId() - lines: ["aaa", "bbb", "ccc"] - ranges: {} + _id: ObjectId(), + lines: ["aaa", "bbb", "ccc"], + ranges: {}, version: 4 - }] - jobs = for doc in @docs - do (doc) => - (callback) => - DocstoreClient.createDoc @project_id, doc._id, doc.lines, doc.version, doc.ranges, callback + }]; + const jobs = Array.from(this.docs).map((doc) => + (doc => { + return callback => { + return DocstoreClient.createDoc(this.project_id, doc._id, doc.lines, doc.version, doc.ranges, callback); + }; + })(doc)); - async.series jobs, (error) => - throw error if error? - DocstoreClient.archiveAllDoc @project_id, (error, @res) => - done() + return async.series(jobs, error => { + if (error != null) { throw error; } + return DocstoreClient.archiveAllDoc(this.project_id, (error, res) => { + this.res = res; + return done(); + }); + }); + }); - it "should archive all the docs", (done) -> - @res.statusCode.should.equal 204 - done() + it("should archive all the docs", function(done) { + this.res.statusCode.should.equal(204); + return done(); + }); - it "should set inS3 and unset lines and ranges in each doc", (done) -> - jobs = for doc in @docs - do (doc) => - (callback) => - db.docs.findOne _id: doc._id, (error, doc) => - should.not.exist doc.lines - should.not.exist doc.ranges - doc.inS3.should.equal true - callback() - async.series jobs, done + it("should set inS3 and unset lines and ranges in each doc", function(done) { + const jobs = Array.from(this.docs).map((doc) => + (doc => { + return callback => { + return db.docs.findOne({_id: doc._id}, (error, doc) => { + should.not.exist(doc.lines); + should.not.exist(doc.ranges); + doc.inS3.should.equal(true); + return callback(); + }); + }; + })(doc)); + return async.series(jobs, done); + }); - it "should set the docs in s3 correctly", (done) -> - jobs = for doc in @docs - do (doc) => - (callback) => - DocstoreClient.getS3Doc @project_id, doc._id, (error, res, s3_doc) => - s3_doc.lines.should.deep.equal doc.lines - s3_doc.ranges.should.deep.equal doc.ranges - callback() - async.series jobs, done + it("should set the docs in s3 correctly", function(done) { + const jobs = Array.from(this.docs).map((doc) => + (doc => { + return callback => { + return DocstoreClient.getS3Doc(this.project_id, doc._id, (error, res, s3_doc) => { + s3_doc.lines.should.deep.equal(doc.lines); + s3_doc.ranges.should.deep.equal(doc.ranges); + return callback(); + }); + }; + })(doc)); + return async.series(jobs, done); + }); - describe "after unarchiving from a request for the project", -> - before (done) -> - DocstoreClient.getAllDocs @project_id, (error, res, @fetched_docs) => - throw error if error? - done() + return describe("after unarchiving from a request for the project", function() { + before(function(done) { + return DocstoreClient.getAllDocs(this.project_id, (error, res, fetched_docs) => { + this.fetched_docs = fetched_docs; + if (error != null) { throw error; } + return done(); + }); + }); - it "should return the docs", (done) -> - for doc, i in @fetched_docs - doc.lines.should.deep.equal @docs[i].lines - done() + it("should return the docs", function(done) { + for (let i = 0; i < this.fetched_docs.length; i++) { + const doc = this.fetched_docs[i]; + doc.lines.should.deep.equal(this.docs[i].lines); + } + return done(); + }); - it "should restore the docs to mongo", (done) -> - jobs = for doc, i in @docs - do (doc, i) => - (callback) => - db.docs.findOne _id: doc._id, (error, doc) => - doc.lines.should.deep.equal @docs[i].lines - doc.ranges.should.deep.equal @docs[i].ranges - should.not.exist doc.inS3 - callback() - async.series jobs, done + return it("should restore the docs to mongo", function(done) { + const jobs = Array.from(this.docs).map((doc, i) => + ((doc, i) => { + return callback => { + return db.docs.findOne({_id: doc._id}, (error, doc) => { + doc.lines.should.deep.equal(this.docs[i].lines); + doc.ranges.should.deep.equal(this.docs[i].ranges); + should.not.exist(doc.inS3); + return callback(); + }); + }; + })(doc, i)); + return async.series(jobs, done); + }); + }); + }); - describe "a deleted doc", -> - before (done) -> - @project_id = ObjectId() - @doc = { - _id: ObjectId() - lines: ["one", "two", "three"] - ranges: {} + describe("a deleted doc", function() { + before(function(done) { + this.project_id = ObjectId(); + this.doc = { + _id: ObjectId(), + lines: ["one", "two", "three"], + ranges: {}, version: 2 - } - DocstoreClient.createDoc @project_id, @doc._id, @doc.lines, @doc.version, @doc.ranges, (error) => - throw error if error? - DocstoreClient.deleteDoc @project_id, @doc._id, (error) => - throw error if error? - DocstoreClient.archiveAllDoc @project_id, (error, @res) => - throw error if error? - done() + }; + return DocstoreClient.createDoc(this.project_id, this.doc._id, this.doc.lines, this.doc.version, this.doc.ranges, error => { + if (error != null) { throw error; } + return DocstoreClient.deleteDoc(this.project_id, this.doc._id, error => { + if (error != null) { throw error; } + return DocstoreClient.archiveAllDoc(this.project_id, (error, res) => { + this.res = res; + if (error != null) { throw error; } + return done(); + }); + }); + }); + }); - it "should successully archive the docs", (done) -> - @res.statusCode.should.equal 204 - done() + it("should successully archive the docs", function(done) { + this.res.statusCode.should.equal(204); + return done(); + }); - it "should set inS3 and unset lines and ranges in each doc", (done) -> - db.docs.findOne _id: @doc._id, (error, doc) => - throw error if error? - should.not.exist doc.lines - should.not.exist doc.ranges - doc.inS3.should.equal true - doc.deleted.should.equal true - done() + it("should set inS3 and unset lines and ranges in each doc", function(done) { + return db.docs.findOne({_id: this.doc._id}, (error, doc) => { + if (error != null) { throw error; } + should.not.exist(doc.lines); + should.not.exist(doc.ranges); + doc.inS3.should.equal(true); + doc.deleted.should.equal(true); + return done(); + }); + }); - it "should set the doc in s3 correctly", (done) -> - DocstoreClient.getS3Doc @project_id, @doc._id, (error, res, s3_doc) => - throw error if error? - s3_doc.lines.should.deep.equal @doc.lines - s3_doc.ranges.should.deep.equal @doc.ranges - done() + it("should set the doc in s3 correctly", function(done) { + return DocstoreClient.getS3Doc(this.project_id, this.doc._id, (error, res, s3_doc) => { + if (error != null) { throw error; } + s3_doc.lines.should.deep.equal(this.doc.lines); + s3_doc.ranges.should.deep.equal(this.doc.ranges); + return done(); + }); + }); - describe "after unarchiving from a request for the project", -> - before (done) -> - DocstoreClient.getAllDocs @project_id, (error, res, @fetched_docs) => - throw error if error? - done() + return describe("after unarchiving from a request for the project", function() { + before(function(done) { + return DocstoreClient.getAllDocs(this.project_id, (error, res, fetched_docs) => { + this.fetched_docs = fetched_docs; + if (error != null) { throw error; } + return done(); + }); + }); - it "should not included the deleted", (done) -> - @fetched_docs.length.should.equal 0 - done() + it("should not included the deleted", function(done) { + this.fetched_docs.length.should.equal(0); + return done(); + }); - it "should restore the doc to mongo", (done) -> - db.docs.findOne _id: @doc._id, (error, doc) => - throw error if error? - doc.lines.should.deep.equal @doc.lines - doc.ranges.should.deep.equal @doc.ranges - should.not.exist doc.inS3 - doc.deleted.should.equal true - done() + return it("should restore the doc to mongo", function(done) { + return db.docs.findOne({_id: this.doc._id}, (error, doc) => { + if (error != null) { throw error; } + doc.lines.should.deep.equal(this.doc.lines); + doc.ranges.should.deep.equal(this.doc.ranges); + should.not.exist(doc.inS3); + doc.deleted.should.equal(true); + return done(); + }); + }); + }); + }); - describe "a doc with large lines", -> - before (done) -> - @project_id = ObjectId() - @timeout 1000 * 30 - quarterMegInBytes = 250000 - big_line = require("crypto").randomBytes(quarterMegInBytes).toString("hex") - @doc = { - _id: ObjectId() - lines: [big_line, big_line, big_line, big_line] - ranges: {} + describe("a doc with large lines", function() { + before(function(done) { + this.project_id = ObjectId(); + this.timeout(1000 * 30); + const quarterMegInBytes = 250000; + const big_line = require("crypto").randomBytes(quarterMegInBytes).toString("hex"); + this.doc = { + _id: ObjectId(), + lines: [big_line, big_line, big_line, big_line], + ranges: {}, version: 2 - } - DocstoreClient.createDoc @project_id, @doc._id, @doc.lines, @doc.version, @doc.ranges, (error) => - throw error if error? - DocstoreClient.archiveAllDoc @project_id, (error, @res) => - throw error if error? - done() + }; + return DocstoreClient.createDoc(this.project_id, this.doc._id, this.doc.lines, this.doc.version, this.doc.ranges, error => { + if (error != null) { throw error; } + return DocstoreClient.archiveAllDoc(this.project_id, (error, res) => { + this.res = res; + if (error != null) { throw error; } + return done(); + }); + }); + }); - it "should successully archive the docs", (done) -> - @res.statusCode.should.equal 204 - done() + it("should successully archive the docs", function(done) { + this.res.statusCode.should.equal(204); + return done(); + }); - it "should set inS3 and unset lines and ranges in each doc", (done) -> - db.docs.findOne _id: @doc._id, (error, doc) => - throw error if error? - should.not.exist doc.lines - should.not.exist doc.ranges - doc.inS3.should.equal true - done() + it("should set inS3 and unset lines and ranges in each doc", function(done) { + return db.docs.findOne({_id: this.doc._id}, (error, doc) => { + if (error != null) { throw error; } + should.not.exist(doc.lines); + should.not.exist(doc.ranges); + doc.inS3.should.equal(true); + return done(); + }); + }); - it "should set the doc in s3 correctly", (done) -> - DocstoreClient.getS3Doc @project_id, @doc._id, (error, res, s3_doc) => - throw error if error? - s3_doc.lines.should.deep.equal @doc.lines - s3_doc.ranges.should.deep.equal @doc.ranges - done() + it("should set the doc in s3 correctly", function(done) { + return DocstoreClient.getS3Doc(this.project_id, this.doc._id, (error, res, s3_doc) => { + if (error != null) { throw error; } + s3_doc.lines.should.deep.equal(this.doc.lines); + s3_doc.ranges.should.deep.equal(this.doc.ranges); + return done(); + }); + }); - describe "after unarchiving from a request for the project", -> - before (done) -> - DocstoreClient.getAllDocs @project_id, (error, res, @fetched_docs) => - throw error if error? - done() + return describe("after unarchiving from a request for the project", function() { + before(function(done) { + return DocstoreClient.getAllDocs(this.project_id, (error, res, fetched_docs) => { + this.fetched_docs = fetched_docs; + if (error != null) { throw error; } + return done(); + }); + }); - it "should restore the doc to mongo", (done) -> - db.docs.findOne _id: @doc._id, (error, doc) => - throw error if error? - doc.lines.should.deep.equal @doc.lines - doc.ranges.should.deep.equal @doc.ranges - should.not.exist doc.inS3 - done() + return it("should restore the doc to mongo", function(done) { + return db.docs.findOne({_id: this.doc._id}, (error, doc) => { + if (error != null) { throw error; } + doc.lines.should.deep.equal(this.doc.lines); + doc.ranges.should.deep.equal(this.doc.ranges); + should.not.exist(doc.inS3); + return done(); + }); + }); + }); + }); - describe "a doc with naughty strings", -> - before (done) -> - @project_id = ObjectId() - @doc = { - _id: ObjectId() - lines: [ "", "undefined", "undef", "null", "NULL", "(null)", "nil", "NIL", "true", "false", "True", "False", "None", "\\", "\\\\", "0", "1", "1.00", "$1.00", "1/2", "1E2", "1E02", "1E+02", "-1", "-1.00", "-$1.00", "-1/2", "-1E2", "-1E02", "-1E+02", "1/0", "0/0", "-2147483648/-1", "-9223372036854775808/-1", "0.00", "0..0", ".", "0.0.0", "0,00", "0,,0", ",", "0,0,0", "0.0/0", "1.0/0.0", "0.0/0.0", "1,0/0,0", "0,0/0,0", "--1", "-", "-.", "-,", "999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999", "NaN", "Infinity", "-Infinity", "0x0", "0xffffffff", "0xffffffffffffffff", "0xabad1dea", "123456789012345678901234567890123456789", "1,000.00", "1 000.00", "1'000.00", "1,000,000.00", "1 000 000.00", "1'000'000.00", "1.000,00", "1 000,00", "1'000,00", "1.000.000,00", "1 000i̳̞v̢͇ḙ͎͟-҉̭̩̼͔m̤̭̫i͕͇̝̦n̗͙ḍ̟ ̯̲͕͞ǫ̟̯̰̲͙̻̝f ̪̰̰̗̖̭̘͘c̦͍̲̞͍̩̙ḥ͚a̮͎̟̙͜ơ̩̹͎s̤.̝̝ ҉Z̡̖̜͖̰̣͉̜a͖̰͙̬͡l̲̫̳͍̩g̡̟̼̱͚̞̬ͅo̗͜.̟", "̦H̬̤̗̤͝e͜ ̜̥̝̻͍̟́w̕h̖̯͓o̝͙̖͎̱̮ ҉̺̙̞̟͈W̷̼̭a̺̪͍į͈͕̭͙̯̜t̶̼̮s̘͙͖̕ ̠̫̠B̻͍͙͉̳ͅe̵h̵̬͇̫͙i̹͓̳̳̮͎̫̕n͟d̴̪̜̖ ̰͉̩͇͙̲͞ͅT͖̼͓̪͢h͏͓̮̻e̬̝̟ͅ ̤̹̝W͙̞̝͔͇͝ͅa͏͓͔̹̼̣l̴͔̰̤̟͔ḽ̫.͕", "Z̮̞̠͙͔ͅḀ̗̞͈̻̗Ḷ͙͎̯̹̞͓G̻O̭̗̮", "˙ɐnbᴉlɐ ɐuƃɐɯ ǝɹolop ʇǝ ǝɹoqɐl ʇn ʇunpᴉpᴉɔuᴉ ɹodɯǝʇ poɯsnᴉǝ op pǝs 'ʇᴉlǝ ƃuᴉɔsᴉdᴉpɐ ɹnʇǝʇɔǝsuoɔ 'ʇǝɯɐ ʇᴉs ɹolop ɯnsdᴉ ɯǝɹo˥", "00˙Ɩ$-", "The quick brown fox jumps over the lazy dog", "𝐓𝐡𝐞 𝐪𝐮𝐢𝐜𝐤 𝐛𝐫𝐨𝐰𝐧 𝐟𝐨𝐱 𝐣𝐮𝐦𝐩𝐬 𝐨𝐯𝐞𝐫 𝐭𝐡𝐞 𝐥𝐚𝐳𝐲 𝐝𝐨𝐠", "𝕿𝖍𝖊 𝖖𝖚𝖎𝖈𝖐 𝖇𝖗𝖔𝖜𝖓 𝖋𝖔𝖝 𝖏𝖚𝖒𝖕𝖘 𝖔𝖛𝖊𝖗 𝖙𝖍𝖊 𝖑𝖆𝖟𝖞 𝖉𝖔𝖌", "𝑻𝒉𝒆 𝒒𝒖𝒊𝒄𝒌 𝒃𝒓𝒐𝒘𝒏 𝒇𝒐𝒙 𝒋𝒖𝒎𝒑𝒔 𝒐𝒗𝒆𝒓 𝒕𝒉𝒆 𝒍𝒂𝒛𝒚 𝒅𝒐𝒈", "𝓣𝓱𝓮 𝓺𝓾𝓲𝓬𝓴 𝓫𝓻𝓸𝔀𝓷 𝓯𝓸𝔁 𝓳𝓾𝓶𝓹𝓼 𝓸𝓿𝓮𝓻 𝓽𝓱𝓮 𝓵𝓪𝔃𝔂 𝓭𝓸𝓰", "𝕋𝕙𝕖 𝕢𝕦𝕚𝕔𝕜 𝕓𝕣𝕠𝕨𝕟 𝕗𝕠𝕩 𝕛𝕦𝕞𝕡𝕤 𝕠𝕧𝕖𝕣 𝕥𝕙𝕖 𝕝𝕒𝕫𝕪 𝕕𝕠𝕘", "𝚃𝚑𝚎 𝚚𝚞𝚒𝚌𝚔 𝚋𝚛𝚘𝚠𝚗 𝚏𝚘𝚡 𝚓𝚞𝚖𝚙𝚜 𝚘𝚟𝚎𝚛 𝚝𝚑𝚎 𝚕𝚊𝚣𝚢 𝚍𝚘𝚐", "⒯⒣⒠ ⒬⒰⒤⒞⒦ ⒝⒭⒪⒲⒩ ⒡⒪⒳ ⒥⒰⒨⒫⒮ ⒪⒱⒠⒭ ⒯⒣⒠ ⒧⒜⒵⒴ ⒟⒪⒢", "", "<script>alert('123');</script>", "", " ", "\">", "'>", ">", "", "< / script >< script >alert(123)< / script >", " onfocus=JaVaSCript:alert(123) autofocus ", "\" onfocus=JaVaSCript:alert(123) autofocus ", "' onfocus=JaVaSCript:alert(123) autofocus ", "<script>alert(123)</script>", "ript>alert(123)ript>", "-->", "\";alert(123);t=\"", "';alert(123);t='", "JavaSCript:alert(123)", ";alert(123);", "src=JaVaSCript:prompt(132)", "\"><\\x3Cscript>javascript:alert(1) ", "'`\"><\\x00script>javascript:alert(1)", "ABC
DEF", "ABC
DEF", "ABC
DEF", "ABC
DEF", "ABC
DEF", "ABC
DEF", "ABC
DEF", "ABC
DEF", "ABC
DEF", "ABC
DEF", "ABC
DEF", "ABC
DEF", "ABC
DEF", "ABC
DEF", "ABC
DEF", "ABC
DEF", "ABC
DEF", "ABC
DEF", "ABC
DEF", "ABC
DEF", "ABC
DEF", "ABC
DEF", "ABC
DEF", "ABC
DEF", "ABC
DEF", "ABC
DEF", "ABC
DEF", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "test", "`\"'>", "`\"'>", "`\"'>", "`\"'>", "`\"'>", "`\"'>", "`\"'>", "`\"'>", "`\"'>", "`\"'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "\"`'>", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "XXX", "javascript:alert(1)\"` `>", "", "", "<a href=http://foo.bar/#x=`y></a><img alt=\"`><img src=x:x onerror=javascript:alert(1)></a>\">", "<!--[if]><script>javascript:alert(1)</script -->", "<!--[if<img src=x onerror=javascript:alert(1)//]> -->", "<script src=\"/\\%(jscript)s\"></script>", "<script src=\"\\\\%(jscript)s\"></script>", "<IMG \"\"\"><SCRIPT>alert(\"XSS\")</SCRIPT>\">", "<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>", "<IMG SRC=# onmouseover=\"alert('xxs')\">", "<IMG SRC= onmouseover=\"alert('xxs')\">", "<IMG onmouseover=\"alert('xxs')\">", "<IMG SRC=javascript:alert('XSS')>", "<IMG SRC=javascript:alert('XSS')>", "<IMG SRC=javascript:alert('XSS')>", "<IMG SRC=\"jav ascript:alert('XSS');\">", "<IMG SRC=\"jav ascript:alert('XSS');\">", "<IMG SRC=\"jav ascript:alert('XSS');\">", "<IMG SRC=\"jav ascript:alert('XSS');\">", "perl -e 'print \"<IMG SRC=java\\0script:alert(\\\"XSS\\\")>\";' > out", "<IMG SRC=\"  javascript:alert('XSS');\">", "<SCRIPT/XSS SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT>", "<BODY onload!#$%&()*~+-_.,:;?@[/|\\]^`=alert(\"XSS\")>", "<SCRIPT/SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT>", "<<SCRIPT>alert(\"XSS\");//<</SCRIPT>", "<SCRIPT SRC=http://ha.ckers.org/xss.js?< B >", "<SCRIPT SRC=//ha.ckers.org/.j>", "<IMG SRC=\"javascript:alert('XSS')\"", "<iframe src=http://ha.ckers.org/scriptlet.html <", "\\\";alert('XSS');//", "<plaintext>", "1;DROP TABLE users", "1'; DROP TABLE users-- 1", "' OR 1=1 -- 1", "' OR '1'='1", "-", "--", "--version", "--help", "$USER", "/dev/null; touch /tmp/blns.fail ; echo", "`touch /tmp/blns.fail`", "$(touch /tmp/blns.fail)", "@{[system \"touch /tmp/blns.fail\"]}", "eval(\"puts 'hello world'\")", "System(\"ls -al /\")", "`ls -al /`", "Kernel.exec(\"ls -al /\")", "Kernel.exit(1)", "%x('ls -al /')", "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><!DOCTYPE foo [ <!ELEMENT foo ANY ><!ENTITY xxe SYSTEM \"file:///etc/passwd\" >]><foo>&xxe;</foo>", "$HOME", "$ENV{'HOME'}", "%d", "%s", "%*.*s", "../../../../../../../../../../../etc/passwd%00", "../../../../../../../../../../../etc/hosts", "() { 0; }; touch /tmp/blns.shellshock1.fail;", "() { _; } >_[$($())] { touch /tmp/blns.shellshock2.fail; }", "CON", "PRN", "AUX", "CLOCK$", "NUL", "A:", "ZZ:", "COM1", "LPT1", "LPT2", "LPT3", "COM2", "COM3", "COM4", "Scunthorpe General Hospital", "Penistone Community Church", "Lightwater Country Park", "Jimmy Clitheroe", "Horniman Museum", "shitake mushrooms", "RomansInSussex.co.uk", "http://www.cum.qc.ca/", "Craig Cockburn, Software Specialist", "Linda Callahan", "Dr. Herman I. Libshitz", "magna cum laude", "Super Bowl XXX", "medieval erection of parapets", "evaluate", "mocha", "expression", "Arsenal canal", "classic", "Tyson Gay", "If you're reading this, you've been in a coma for almost 20 years now. We're trying a new technique. We don't know where this message will end up in your dream, but we hope it works. Please wake up, we miss you.", "Roses are \u001b[0;31mred\u001b[0m, violets are \u001b[0;34mblue. Hope you enjoy terminal hue", "But now...\u001b[20Cfor my greatest trick...\u001b[8m", "The quic\b\b\b\b\b\bk brown fo\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007x... [Beeeep]", "Powerلُلُصّبُلُلصّبُررً ॣ ॣh ॣ ॣ冗" ] - ranges: {} + describe("a doc with naughty strings", function() { + before(function(done) { + this.project_id = ObjectId(); + this.doc = { + _id: ObjectId(), + lines: [ "", "undefined", "undef", "null", "NULL", "(null)", "nil", "NIL", "true", "false", "True", "False", "None", "\\", "\\\\", "0", "1", "1.00", "$1.00", "1/2", "1E2", "1E02", "1E+02", "-1", "-1.00", "-$1.00", "-1/2", "-1E2", "-1E02", "-1E+02", "1/0", "0/0", "-2147483648/-1", "-9223372036854775808/-1", "0.00", "0..0", ".", "0.0.0", "0,00", "0,,0", ",", "0,0,0", "0.0/0", "1.0/0.0", "0.0/0.0", "1,0/0,0", "0,0/0,0", "--1", "-", "-.", "-,", "999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999", "NaN", "Infinity", "-Infinity", "0x0", "0xffffffff", "0xffffffffffffffff", "0xabad1dea", "123456789012345678901234567890123456789", "1,000.00", "1 000.00", "1'000.00", "1,000,000.00", "1 000 000.00", "1'000'000.00", "1.000,00", "1 000,00", "1'000,00", "1.000.000,00", "1 000i̳̞v̢͇ḙ͎͟-҉̭̩̼͔m̤̭̫i͕͇̝̦n̗͙ḍ̟ ̯̲͕͞ǫ̟̯̰̲͙̻̝f ̪̰̰̗̖̭̘͘c̦͍̲̞͍̩̙ḥ͚a̮͎̟̙͜ơ̩̹͎s̤.̝̝ ҉Z̡̖̜͖̰̣͉̜a͖̰͙̬͡l̲̫̳͍̩g̡̟̼̱͚̞̬ͅo̗͜.̟", "̦H̬̤̗̤͝e͜ ̜̥̝̻͍̟́w̕h̖̯͓o̝͙̖͎̱̮ ҉̺̙̞̟͈W̷̼̭a̺̪͍į͈͕̭͙̯̜t̶̼̮s̘͙͖̕ ̠̫̠B̻͍͙͉̳ͅe̵h̵̬͇̫͙i̹͓̳̳̮͎̫̕n͟d̴̪̜̖ ̰͉̩͇͙̲͞ͅT͖̼͓̪͢h͏͓̮̻e̬̝̟ͅ ̤̹̝W͙̞̝͔͇͝ͅa͏͓͔̹̼̣l̴͔̰̤̟͔ḽ̫.͕", "Z̮̞̠͙͔ͅḀ̗̞͈̻̗Ḷ͙͎̯̹̞͓G̻O̭̗̮", "˙ɐnbᴉlɐ ɐuƃɐɯ ǝɹolop ʇǝ ǝɹoqɐl ʇn ʇunpᴉpᴉɔuᴉ ɹodɯǝʇ poɯsnᴉǝ op pǝs 'ʇᴉlǝ ƃuᴉɔsᴉdᴉpɐ ɹnʇǝʇɔǝsuoɔ 'ʇǝɯɐ ʇᴉs ɹolop ɯnsdᴉ ɯǝɹo˥", "00˙Ɩ$-", "The quick brown fox jumps over the lazy dog", "𝐓𝐡𝐞 𝐪𝐮𝐢𝐜𝐤 𝐛𝐫𝐨𝐰𝐧 𝐟𝐨𝐱 𝐣𝐮𝐦𝐩𝐬 𝐨𝐯𝐞𝐫 𝐭𝐡𝐞 𝐥𝐚𝐳𝐲 𝐝𝐨𝐠", "𝕿𝖍𝖊 𝖖𝖚𝖎𝖈𝖐 𝖇𝖗𝖔𝖜𝖓 𝖋𝖔𝖝 𝖏𝖚𝖒𝖕𝖘 𝖔𝖛𝖊𝖗 𝖙𝖍𝖊 𝖑𝖆𝖟𝖞 𝖉𝖔𝖌", "𝑻𝒉𝒆 𝒒𝒖𝒊𝒄𝒌 𝒃𝒓𝒐𝒘𝒏 𝒇𝒐𝒙 𝒋𝒖𝒎𝒑𝒔 𝒐𝒗𝒆𝒓 𝒕𝒉𝒆 𝒍𝒂𝒛𝒚 𝒅𝒐𝒈", "𝓣𝓱𝓮 𝓺𝓾𝓲𝓬𝓴 𝓫𝓻𝓸𝔀𝓷 𝓯𝓸𝔁 𝓳𝓾𝓶𝓹𝓼 𝓸𝓿𝓮𝓻 𝓽𝓱𝓮 𝓵𝓪𝔃𝔂 𝓭𝓸𝓰", "𝕋𝕙𝕖 𝕢𝕦𝕚𝕔𝕜 𝕓𝕣𝕠𝕨𝕟 𝕗𝕠𝕩 𝕛𝕦𝕞𝕡𝕤 𝕠𝕧𝕖𝕣 𝕥𝕙𝕖 𝕝𝕒𝕫𝕪 𝕕𝕠𝕘", "𝚃𝚑𝚎 𝚚𝚞𝚒𝚌𝚔 𝚋𝚛𝚘𝚠𝚗 𝚏𝚘𝚡 𝚓𝚞𝚖𝚙𝚜 𝚘𝚟𝚎𝚛 𝚝𝚑𝚎 𝚕𝚊𝚣𝚢 𝚍𝚘𝚐", "⒯⒣⒠ ⒬⒰⒤⒞⒦ ⒝⒭⒪⒲⒩ ⒡⒪⒳ ⒥⒰⒨⒫⒮ ⒪⒱⒠⒭ ⒯⒣⒠ ⒧⒜⒵⒴ ⒟⒪⒢", "<script>alert(123)</script>", "<script>alert('123');</script>", "<img src=x onerror=alert(123) />", "<svg><script>123<1>alert(123)</script> ", "\"><script>alert(123)</script>", "'><script>alert(123)</script>", "><script>alert(123)</script>", "</script><script>alert(123)</script>", "< / script >< script >alert(123)< / script >", " onfocus=JaVaSCript:alert(123) autofocus ", "\" onfocus=JaVaSCript:alert(123) autofocus ", "' onfocus=JaVaSCript:alert(123) autofocus ", "<script>alert(123)</script>", "<sc<script>ript>alert(123)</sc</script>ript>", "--><script>alert(123)</script>", "\";alert(123);t=\"", "';alert(123);t='", "JavaSCript:alert(123)", ";alert(123);", "src=JaVaSCript:prompt(132)", "\"><script>alert(123);</script x=\"", "'><script>alert(123);</script x='", "><script>alert(123);</script x=", "\" autofocus onkeyup=\"javascript:alert(123)", "' autofocus onkeyup='javascript:alert(123)", "<script\\x20type=\"text/javascript\">javascript:alert(1);</script>", "<script\\x3Etype=\"text/javascript\">javascript:alert(1);</script>", "<script\\x0Dtype=\"text/javascript\">javascript:alert(1);</script>", "<script\\x09type=\"text/javascript\">javascript:alert(1);</script>", "<script\\x0Ctype=\"text/javascript\">javascript:alert(1);</script>", "<script\\x2Ftype=\"text/javascript\">javascript:alert(1);</script>", "<script\\x0Atype=\"text/javascript\">javascript:alert(1);</script>", "'`\"><\\x3Cscript>javascript:alert(1)</script> ", "'`\"><\\x00script>javascript:alert(1)</script>", "ABC<div style=\"x\\x3Aexpression(javascript:alert(1)\">DEF", "ABC<div style=\"x:expression\\x5C(javascript:alert(1)\">DEF", "ABC<div style=\"x:expression\\x00(javascript:alert(1)\">DEF", "ABC<div style=\"x:exp\\x00ression(javascript:alert(1)\">DEF", "ABC<div style=\"x:exp\\x5Cression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\x0Aexpression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\x09expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xE3\\x80\\x80expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xE2\\x80\\x84expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xC2\\xA0expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xE2\\x80\\x80expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xE2\\x80\\x8Aexpression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\x0Dexpression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\x0Cexpression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xE2\\x80\\x87expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xEF\\xBB\\xBFexpression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\x20expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xE2\\x80\\x88expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\x00expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xE2\\x80\\x8Bexpression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xE2\\x80\\x86expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xE2\\x80\\x85expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xE2\\x80\\x82expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\x0Bexpression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xE2\\x80\\x81expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xE2\\x80\\x83expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xE2\\x80\\x89expression(javascript:alert(1)\">DEF", "<a href=\"\\x0Bjavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x0Fjavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xC2\\xA0javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x05javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE1\\xA0\\x8Ejavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x18javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x11javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\x88javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\x89javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\x80javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x17javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x03javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x0Ejavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x1Ajavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x00javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x10javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\x82javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x20javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x13javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x09javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\x8Ajavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x14javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x19javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\xAFjavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x1Fjavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\x81javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x1Djavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\x87javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x07javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE1\\x9A\\x80javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\x83javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x04javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x01javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x08javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\x84javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\x86javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE3\\x80\\x80javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x12javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x0Djavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x0Ajavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x0Cjavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x15javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\xA8javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x16javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x02javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x1Bjavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x06javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\xA9javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\x85javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x1Ejavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x81\\x9Fjavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x1Cjavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"javascript\\x00:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"javascript\\x3A:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"javascript\\x09:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"javascript\\x0D:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"javascript\\x0A:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "`\"'><img src=xxx:x \\x0Aonerror=javascript:alert(1)>", "`\"'><img src=xxx:x \\x22onerror=javascript:alert(1)>", "`\"'><img src=xxx:x \\x0Bonerror=javascript:alert(1)>", "`\"'><img src=xxx:x \\x0Donerror=javascript:alert(1)>", "`\"'><img src=xxx:x \\x2Fonerror=javascript:alert(1)>", "`\"'><img src=xxx:x \\x09onerror=javascript:alert(1)>", "`\"'><img src=xxx:x \\x0Conerror=javascript:alert(1)>", "`\"'><img src=xxx:x \\x00onerror=javascript:alert(1)>", "`\"'><img src=xxx:x \\x27onerror=javascript:alert(1)>", "`\"'><img src=xxx:x \\x20onerror=javascript:alert(1)>", "\"`'><script>\\x3Bjavascript:alert(1)</script>", "\"`'><script>\\x0Djavascript:alert(1)</script>", "\"`'><script>\\xEF\\xBB\\xBFjavascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\x81javascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\x84javascript:alert(1)</script>", "\"`'><script>\\xE3\\x80\\x80javascript:alert(1)</script>", "\"`'><script>\\x09javascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\x89javascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\x85javascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\x88javascript:alert(1)</script>", "\"`'><script>\\x00javascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\xA8javascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\x8Ajavascript:alert(1)</script>", "\"`'><script>\\xE1\\x9A\\x80javascript:alert(1)</script>", "\"`'><script>\\x0Cjavascript:alert(1)</script>", "\"`'><script>\\x2Bjavascript:alert(1)</script>", "\"`'><script>\\xF0\\x90\\x96\\x9Ajavascript:alert(1)</script>", "\"`'><script>-javascript:alert(1)</script>", "\"`'><script>\\x0Ajavascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\xAFjavascript:alert(1)</script>", "\"`'><script>\\x7Ejavascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\x87javascript:alert(1)</script>", "\"`'><script>\\xE2\\x81\\x9Fjavascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\xA9javascript:alert(1)</script>", "\"`'><script>\\xC2\\x85javascript:alert(1)</script>", "\"`'><script>\\xEF\\xBF\\xAEjavascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\x83javascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\x8Bjavascript:alert(1)</script>", "\"`'><script>\\xEF\\xBF\\xBEjavascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\x80javascript:alert(1)</script>", "\"`'><script>\\x21javascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\x82javascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\x86javascript:alert(1)</script>", "\"`'><script>\\xE1\\xA0\\x8Ejavascript:alert(1)</script>", "\"`'><script>\\x0Bjavascript:alert(1)</script>", "\"`'><script>\\x20javascript:alert(1)</script>", "\"`'><script>\\xC2\\xA0javascript:alert(1)</script>", "<img \\x00src=x onerror=\"alert(1)\">", "<img \\x47src=x onerror=\"javascript:alert(1)\">", "<img \\x11src=x onerror=\"javascript:alert(1)\">", "<img \\x12src=x onerror=\"javascript:alert(1)\">", "<img\\x47src=x onerror=\"javascript:alert(1)\">", "<img\\x10src=x onerror=\"javascript:alert(1)\">", "<img\\x13src=x onerror=\"javascript:alert(1)\">", "<img\\x32src=x onerror=\"javascript:alert(1)\">", "<img\\x47src=x onerror=\"javascript:alert(1)\">", "<img\\x11src=x onerror=\"javascript:alert(1)\">", "<img \\x47src=x onerror=\"javascript:alert(1)\">", "<img \\x34src=x onerror=\"javascript:alert(1)\">", "<img \\x39src=x onerror=\"javascript:alert(1)\">", "<img \\x00src=x onerror=\"javascript:alert(1)\">", "<img src\\x09=x onerror=\"javascript:alert(1)\">", "<img src\\x10=x onerror=\"javascript:alert(1)\">", "<img src\\x13=x onerror=\"javascript:alert(1)\">", "<img src\\x32=x onerror=\"javascript:alert(1)\">", "<img src\\x12=x onerror=\"javascript:alert(1)\">", "<img src\\x11=x onerror=\"javascript:alert(1)\">", "<img src\\x00=x onerror=\"javascript:alert(1)\">", "<img src\\x47=x onerror=\"javascript:alert(1)\">", "<img src=x\\x09onerror=\"javascript:alert(1)\">", "<img src=x\\x10onerror=\"javascript:alert(1)\">", "<img src=x\\x11onerror=\"javascript:alert(1)\">", "<img src=x\\x12onerror=\"javascript:alert(1)\">", "<img src=x\\x13onerror=\"javascript:alert(1)\">", "<img[a][b][c]src[d]=x[e]onerror=[f]\"alert(1)\">", "<img src=x onerror=\\x09\"javascript:alert(1)\">", "<img src=x onerror=\\x10\"javascript:alert(1)\">", "<img src=x onerror=\\x11\"javascript:alert(1)\">", "<img src=x onerror=\\x12\"javascript:alert(1)\">", "<img src=x onerror=\\x32\"javascript:alert(1)\">", "<img src=x onerror=\\x00\"javascript:alert(1)\">", "<a href=java script:javascript:alert(1)>XXX</a>", "<img src=\"x` `<script>javascript:alert(1)</script>\"` `>", "<img src onerror /\" '\"= alt=javascript:alert(1)//\">", "<title onpropertychange=javascript:alert(1)>", "<a href=http://foo.bar/#x=`y></a><img alt=\"`><img src=x:x onerror=javascript:alert(1)></a>\">", "<!--[if]><script>javascript:alert(1)</script -->", "<!--[if<img src=x onerror=javascript:alert(1)//]> -->", "<script src=\"/\\%(jscript)s\"></script>", "<script src=\"\\\\%(jscript)s\"></script>", "<IMG \"\"\"><SCRIPT>alert(\"XSS\")</SCRIPT>\">", "<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>", "<IMG SRC=# onmouseover=\"alert('xxs')\">", "<IMG SRC= onmouseover=\"alert('xxs')\">", "<IMG onmouseover=\"alert('xxs')\">", "<IMG SRC=javascript:alert('XSS')>", "<IMG SRC=javascript:alert('XSS')>", "<IMG SRC=javascript:alert('XSS')>", "<IMG SRC=\"jav ascript:alert('XSS');\">", "<IMG SRC=\"jav ascript:alert('XSS');\">", "<IMG SRC=\"jav ascript:alert('XSS');\">", "<IMG SRC=\"jav ascript:alert('XSS');\">", "perl -e 'print \"<IMG SRC=java\\0script:alert(\\\"XSS\\\")>\";' > out", "<IMG SRC=\"  javascript:alert('XSS');\">", "<SCRIPT/XSS SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT>", "<BODY onload!#$%&()*~+-_.,:;?@[/|\\]^`=alert(\"XSS\")>", "<SCRIPT/SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT>", "<<SCRIPT>alert(\"XSS\");//<</SCRIPT>", "<SCRIPT SRC=http://ha.ckers.org/xss.js?< B >", "<SCRIPT SRC=//ha.ckers.org/.j>", "<IMG SRC=\"javascript:alert('XSS')\"", "<iframe src=http://ha.ckers.org/scriptlet.html <", "\\\";alert('XSS');//", "<plaintext>", "1;DROP TABLE users", "1'; DROP TABLE users-- 1", "' OR 1=1 -- 1", "' OR '1'='1", "-", "--", "--version", "--help", "$USER", "/dev/null; touch /tmp/blns.fail ; echo", "`touch /tmp/blns.fail`", "$(touch /tmp/blns.fail)", "@{[system \"touch /tmp/blns.fail\"]}", "eval(\"puts 'hello world'\")", "System(\"ls -al /\")", "`ls -al /`", "Kernel.exec(\"ls -al /\")", "Kernel.exit(1)", "%x('ls -al /')", "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><!DOCTYPE foo [ <!ELEMENT foo ANY ><!ENTITY xxe SYSTEM \"file:///etc/passwd\" >]><foo>&xxe;</foo>", "$HOME", "$ENV{'HOME'}", "%d", "%s", "%*.*s", "../../../../../../../../../../../etc/passwd%00", "../../../../../../../../../../../etc/hosts", "() { 0; }; touch /tmp/blns.shellshock1.fail;", "() { _; } >_[$($())] { touch /tmp/blns.shellshock2.fail; }", "CON", "PRN", "AUX", "CLOCK$", "NUL", "A:", "ZZ:", "COM1", "LPT1", "LPT2", "LPT3", "COM2", "COM3", "COM4", "Scunthorpe General Hospital", "Penistone Community Church", "Lightwater Country Park", "Jimmy Clitheroe", "Horniman Museum", "shitake mushrooms", "RomansInSussex.co.uk", "http://www.cum.qc.ca/", "Craig Cockburn, Software Specialist", "Linda Callahan", "Dr. Herman I. Libshitz", "magna cum laude", "Super Bowl XXX", "medieval erection of parapets", "evaluate", "mocha", "expression", "Arsenal canal", "classic", "Tyson Gay", "If you're reading this, you've been in a coma for almost 20 years now. We're trying a new technique. We don't know where this message will end up in your dream, but we hope it works. Please wake up, we miss you.", "Roses are \u001b[0;31mred\u001b[0m, violets are \u001b[0;34mblue. Hope you enjoy terminal hue", "But now...\u001b[20Cfor my greatest trick...\u001b[8m", "The quic\b\b\b\b\b\bk brown fo\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007x... [Beeeep]", "Powerلُلُصّبُلُلصّبُررً ॣ ॣh ॣ ॣ冗" ], + ranges: {}, version: 2 - } - DocstoreClient.createDoc @project_id, @doc._id, @doc.lines, @doc.version, @doc.ranges, (error) => - throw error if error? - DocstoreClient.archiveAllDoc @project_id, (error, @res) => - throw error if error? - done() + }; + return DocstoreClient.createDoc(this.project_id, this.doc._id, this.doc.lines, this.doc.version, this.doc.ranges, error => { + if (error != null) { throw error; } + return DocstoreClient.archiveAllDoc(this.project_id, (error, res) => { + this.res = res; + if (error != null) { throw error; } + return done(); + }); + }); + }); - it "should successully archive the docs", (done) -> - @res.statusCode.should.equal 204 - done() + it("should successully archive the docs", function(done) { + this.res.statusCode.should.equal(204); + return done(); + }); - it "should set inS3 and unset lines and ranges in each doc", (done) -> - db.docs.findOne _id: @doc._id, (error, doc) => - throw error if error? - should.not.exist doc.lines - should.not.exist doc.ranges - doc.inS3.should.equal true - done() + it("should set inS3 and unset lines and ranges in each doc", function(done) { + return db.docs.findOne({_id: this.doc._id}, (error, doc) => { + if (error != null) { throw error; } + should.not.exist(doc.lines); + should.not.exist(doc.ranges); + doc.inS3.should.equal(true); + return done(); + }); + }); - it "should set the doc in s3 correctly", (done) -> - DocstoreClient.getS3Doc @project_id, @doc._id, (error, res, s3_doc) => - throw error if error? - s3_doc.lines.should.deep.equal @doc.lines - s3_doc.ranges.should.deep.equal @doc.ranges - done() + it("should set the doc in s3 correctly", function(done) { + return DocstoreClient.getS3Doc(this.project_id, this.doc._id, (error, res, s3_doc) => { + if (error != null) { throw error; } + s3_doc.lines.should.deep.equal(this.doc.lines); + s3_doc.ranges.should.deep.equal(this.doc.ranges); + return done(); + }); + }); - describe "after unarchiving from a request for the project", -> - before (done) -> - DocstoreClient.getAllDocs @project_id, (error, res, @fetched_docs) => - throw error if error? - done() + return describe("after unarchiving from a request for the project", function() { + before(function(done) { + return DocstoreClient.getAllDocs(this.project_id, (error, res, fetched_docs) => { + this.fetched_docs = fetched_docs; + if (error != null) { throw error; } + return done(); + }); + }); - it "should restore the doc to mongo", (done) -> - db.docs.findOne _id: @doc._id, (error, doc) => - throw error if error? - doc.lines.should.deep.equal @doc.lines - doc.ranges.should.deep.equal @doc.ranges - should.not.exist doc.inS3 - done() + return it("should restore the doc to mongo", function(done) { + return db.docs.findOne({_id: this.doc._id}, (error, doc) => { + if (error != null) { throw error; } + doc.lines.should.deep.equal(this.doc.lines); + doc.ranges.should.deep.equal(this.doc.ranges); + should.not.exist(doc.inS3); + return done(); + }); + }); + }); + }); - describe "a doc with ranges", -> - before (done) -> - @project_id = ObjectId() - @doc = { - _id: ObjectId() - lines: ["one", "two", "three"] + describe("a doc with ranges", function() { + before(function(done) { + this.project_id = ObjectId(); + this.doc = { + _id: ObjectId(), + lines: ["one", "two", "three"], ranges: { changes: [{ id : ObjectId(), - op : { "i" : "foo", "p" : 24 } + op : { "i" : "foo", "p" : 24 }, metadata : { "user_id" : ObjectId(), "ts" : new Date("2017-01-27T16:10:44.194Z") } }, { id : ObjectId(), - op : { "d" : "bar", "p" : 50 } + op : { "d" : "bar", "p" : 50 }, metadata : { "user_id" : ObjectId(), "ts" : new Date("2017-01-27T18:10:44.194Z") } - }] + }], comments: [{ id: ObjectId(), op: { "c" : "comment", "p" : 284, "t" : ObjectId() }, metadata: { "user_id" : ObjectId(), "ts" : new Date("2017-01-26T14:22:04.869Z") } }] - } + }, version: 2 - } - DocstoreClient.createDoc @project_id, @doc._id, @doc.lines, @doc.version, @doc.ranges, (error) => - throw error if error? - DocstoreClient.archiveAllDoc @project_id, (error, @res) => - throw error if error? - done() + }; + return DocstoreClient.createDoc(this.project_id, this.doc._id, this.doc.lines, this.doc.version, this.doc.ranges, error => { + if (error != null) { throw error; } + return DocstoreClient.archiveAllDoc(this.project_id, (error, res) => { + this.res = res; + if (error != null) { throw error; } + return done(); + }); + }); + }); - it "should successully archive the docs", (done) -> - @res.statusCode.should.equal 204 - done() + it("should successully archive the docs", function(done) { + this.res.statusCode.should.equal(204); + return done(); + }); - it "should set inS3 and unset lines and ranges in each doc", (done) -> - db.docs.findOne _id: @doc._id, (error, doc) => - throw error if error? - should.not.exist doc.lines - should.not.exist doc.ranges - doc.inS3.should.equal true - done() + it("should set inS3 and unset lines and ranges in each doc", function(done) { + return db.docs.findOne({_id: this.doc._id}, (error, doc) => { + if (error != null) { throw error; } + should.not.exist(doc.lines); + should.not.exist(doc.ranges); + doc.inS3.should.equal(true); + return done(); + }); + }); - it "should set the doc in s3 correctly", (done) -> - DocstoreClient.getS3Doc @project_id, @doc._id, (error, res, s3_doc) => - throw error if error? - s3_doc.lines.should.deep.equal @doc.lines - ranges = JSON.parse(JSON.stringify(@doc.ranges)) # ObjectId -> String - s3_doc.ranges.should.deep.equal ranges - done() + it("should set the doc in s3 correctly", function(done) { + return DocstoreClient.getS3Doc(this.project_id, this.doc._id, (error, res, s3_doc) => { + if (error != null) { throw error; } + s3_doc.lines.should.deep.equal(this.doc.lines); + const ranges = JSON.parse(JSON.stringify(this.doc.ranges)); // ObjectId -> String + s3_doc.ranges.should.deep.equal(ranges); + return done(); + }); + }); - describe "after unarchiving from a request for the project", -> - before (done) -> - DocstoreClient.getAllDocs @project_id, (error, res, @fetched_docs) => - throw error if error? - done() + return describe("after unarchiving from a request for the project", function() { + before(function(done) { + return DocstoreClient.getAllDocs(this.project_id, (error, res, fetched_docs) => { + this.fetched_docs = fetched_docs; + if (error != null) { throw error; } + return done(); + }); + }); - it "should restore the doc to mongo", (done) -> - db.docs.findOne _id: @doc._id, (error, doc) => - throw error if error? - doc.lines.should.deep.equal @doc.lines - doc.ranges.should.deep.equal @doc.ranges - should.not.exist doc.inS3 - done() + return it("should restore the doc to mongo", function(done) { + return db.docs.findOne({_id: this.doc._id}, (error, doc) => { + if (error != null) { throw error; } + doc.lines.should.deep.equal(this.doc.lines); + doc.ranges.should.deep.equal(this.doc.ranges); + should.not.exist(doc.inS3); + return done(); + }); + }); + }); + }); - describe "a doc that is archived twice", -> - before (done) -> - @project_id = ObjectId() - @doc = { - _id: ObjectId() - lines: ["abc", "def", "ghi"] - ranges: {} + describe("a doc that is archived twice", function() { + before(function(done) { + this.project_id = ObjectId(); + this.doc = { + _id: ObjectId(), + lines: ["abc", "def", "ghi"], + ranges: {}, version: 2 - } - DocstoreClient.createDoc @project_id, @doc._id, @doc.lines, @doc.version, @doc.ranges, (error) => - throw error if error? - DocstoreClient.archiveAllDoc @project_id, (error, @res) => - throw error if error? - @res.statusCode.should.equal 204 - DocstoreClient.archiveAllDoc @project_id, (error, @res) => - throw error if error? - @res.statusCode.should.equal 204 - done() + }; + return DocstoreClient.createDoc(this.project_id, this.doc._id, this.doc.lines, this.doc.version, this.doc.ranges, error => { + if (error != null) { throw error; } + return DocstoreClient.archiveAllDoc(this.project_id, (error, res) => { + this.res = res; + if (error != null) { throw error; } + this.res.statusCode.should.equal(204); + return DocstoreClient.archiveAllDoc(this.project_id, (error, res1) => { + this.res = res1; + if (error != null) { throw error; } + this.res.statusCode.should.equal(204); + return done(); + }); + }); + }); + }); - it "should set inS3 and unset lines and ranges in each doc", (done) -> - db.docs.findOne _id: @doc._id, (error, doc) => - throw error if error? - should.not.exist doc.lines - should.not.exist doc.ranges - doc.inS3.should.equal true - done() + it("should set inS3 and unset lines and ranges in each doc", function(done) { + return db.docs.findOne({_id: this.doc._id}, (error, doc) => { + if (error != null) { throw error; } + should.not.exist(doc.lines); + should.not.exist(doc.ranges); + doc.inS3.should.equal(true); + return done(); + }); + }); - it "should set the doc in s3 correctly", (done) -> - DocstoreClient.getS3Doc @project_id, @doc._id, (error, res, s3_doc) => - throw error if error? - s3_doc.lines.should.deep.equal @doc.lines - s3_doc.ranges.should.deep.equal @doc.ranges - done() + it("should set the doc in s3 correctly", function(done) { + return DocstoreClient.getS3Doc(this.project_id, this.doc._id, (error, res, s3_doc) => { + if (error != null) { throw error; } + s3_doc.lines.should.deep.equal(this.doc.lines); + s3_doc.ranges.should.deep.equal(this.doc.ranges); + return done(); + }); + }); - describe "after unarchiving from a request for the project", -> - before (done) -> - DocstoreClient.getAllDocs @project_id, (error, res, @fetched_docs) => - throw error if error? - done() + return describe("after unarchiving from a request for the project", function() { + before(function(done) { + return DocstoreClient.getAllDocs(this.project_id, (error, res, fetched_docs) => { + this.fetched_docs = fetched_docs; + if (error != null) { throw error; } + return done(); + }); + }); - it "should restore the doc to mongo", (done) -> - db.docs.findOne _id: @doc._id, (error, doc) => - throw error if error? - doc.lines.should.deep.equal @doc.lines - doc.ranges.should.deep.equal @doc.ranges - should.not.exist doc.inS3 - done() + return it("should restore the doc to mongo", function(done) { + return db.docs.findOne({_id: this.doc._id}, (error, doc) => { + if (error != null) { throw error; } + doc.lines.should.deep.equal(this.doc.lines); + doc.ranges.should.deep.equal(this.doc.ranges); + should.not.exist(doc.inS3); + return done(); + }); + }); + }); + }); - describe "a doc with the old schema (just an array of lines)", -> - before (done) -> - @project_id = ObjectId() - @doc = { - _id: ObjectId() - lines: ["abc", "def", "ghi"] - ranges: {} + return describe("a doc with the old schema (just an array of lines)", function() { + before(function(done) { + this.project_id = ObjectId(); + this.doc = { + _id: ObjectId(), + lines: ["abc", "def", "ghi"], + ranges: {}, version: 2 - } - options = DocArchiveManager.buildS3Options("#{@project_id}/#{@doc._id}") - options.json = @doc.lines - request.put options, (error, res, body) => - throw error if error? - res.statusCode.should.equal 200 - db.docs.insert { - project_id: @project_id - _id: @doc._id - rev: @doc.version + }; + const options = DocArchiveManager.buildS3Options(`${this.project_id}/${this.doc._id}`); + options.json = this.doc.lines; + return request.put(options, (error, res, body) => { + if (error != null) { throw error; } + res.statusCode.should.equal(200); + return db.docs.insert({ + project_id: this.project_id, + _id: this.doc._id, + rev: this.doc.version, inS3: true - }, (error) => - throw error if error? - DocstoreClient.getAllDocs @project_id, (error, res, @fetched_docs) => - throw error if error? - done() + }, error => { + if (error != null) { throw error; } + return DocstoreClient.getAllDocs(this.project_id, (error, res, fetched_docs) => { + this.fetched_docs = fetched_docs; + if (error != null) { throw error; } + return done(); + }); + }); + }); + }); - it "should restore the doc to mongo", (done) -> - db.docs.findOne _id: @doc._id, (error, doc) => - throw error if error? - doc.lines.should.deep.equal @doc.lines - should.not.exist doc.inS3 - done() + it("should restore the doc to mongo", function(done) { + return db.docs.findOne({_id: this.doc._id}, (error, doc) => { + if (error != null) { throw error; } + doc.lines.should.deep.equal(this.doc.lines); + should.not.exist(doc.inS3); + return done(); + }); + }); - it "should return the doc", (done) -> - @fetched_docs[0].lines.should.deep.equal @doc.lines - done() + return it("should return the doc", function(done) { + this.fetched_docs[0].lines.should.deep.equal(this.doc.lines); + return done(); + }); + }); +}); diff --git a/services/docstore/test/acceptance/coffee/DeletingDocsTests.js b/services/docstore/test/acceptance/coffee/DeletingDocsTests.js index 4aac25902e..3fd2bf240d 100644 --- a/services/docstore/test/acceptance/coffee/DeletingDocsTests.js +++ b/services/docstore/test/acceptance/coffee/DeletingDocsTests.js @@ -1,85 +1,122 @@ -sinon = require "sinon" -chai = require("chai") -chai.should() -{db, ObjectId} = require "../../../app/js/mongojs" -expect = chai.expect -DocstoreApp = require "./helpers/DocstoreApp" +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS207: Consider shorter variations of null checks + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +const sinon = require("sinon"); +const chai = require("chai"); +chai.should(); +const {db, ObjectId} = require("../../../app/js/mongojs"); +const { + expect +} = chai; +const DocstoreApp = require("./helpers/DocstoreApp"); -DocstoreClient = require "./helpers/DocstoreClient" +const DocstoreClient = require("./helpers/DocstoreClient"); -describe "Deleting a doc", -> - beforeEach (done) -> - @project_id = ObjectId() - @doc_id = ObjectId() - @lines = ["original", "lines"] - @version = 42 - @ranges = [] - DocstoreApp.ensureRunning => - DocstoreClient.createDoc @project_id, @doc_id, @lines, @version, @ranges, (error) => - throw error if error? - done() +describe("Deleting a doc", function() { + beforeEach(function(done) { + this.project_id = ObjectId(); + this.doc_id = ObjectId(); + this.lines = ["original", "lines"]; + this.version = 42; + this.ranges = []; + return DocstoreApp.ensureRunning(() => { + return DocstoreClient.createDoc(this.project_id, this.doc_id, this.lines, this.version, this.ranges, error => { + if (error != null) { throw error; } + return done(); + }); + }); + }); - describe "when the doc exists", -> - beforeEach (done) -> - DocstoreClient.deleteDoc @project_id, @doc_id, (error, @res, doc) => - done() + describe("when the doc exists", function() { + beforeEach(function(done) { + return DocstoreClient.deleteDoc(this.project_id, this.doc_id, (error, res, doc) => { + this.res = res; + return done(); + }); + }); - afterEach (done) -> - db.docs.remove({_id: @doc_id}, done) + afterEach(function(done) { + return db.docs.remove({_id: this.doc_id}, done); + }); - it "should insert a deleted doc into the docs collection", (done) -> - db.docs.find _id: @doc_id, (error, docs) => - docs[0]._id.should.deep.equal @doc_id - docs[0].lines.should.deep.equal @lines - docs[0].deleted.should.equal true - done() + return it("should insert a deleted doc into the docs collection", function(done) { + return db.docs.find({_id: this.doc_id}, (error, docs) => { + docs[0]._id.should.deep.equal(this.doc_id); + docs[0].lines.should.deep.equal(this.lines); + docs[0].deleted.should.equal(true); + return done(); + }); + }); + }); - describe "when the doc does not exist", -> - it "should return a 404", (done) -> - missing_doc_id = ObjectId() - DocstoreClient.deleteDoc @project_id, missing_doc_id, (error, res, doc) -> - res.statusCode.should.equal 404 - done() + return describe("when the doc does not exist", () => it("should return a 404", function(done) { + const missing_doc_id = ObjectId(); + return DocstoreClient.deleteDoc(this.project_id, missing_doc_id, function(error, res, doc) { + res.statusCode.should.equal(404); + return done(); + }); + })); +}); -describe "Destroying a project's documents", -> - describe "when the doc exists", -> - beforeEach (done) -> - db.docOps.insert {doc_id: ObjectId(@doc_id), version: 1}, (err) -> - return done(err) if err? - DocstoreClient.destroyAllDoc @project_id, done +describe("Destroying a project's documents", function() { + describe("when the doc exists", function() { + beforeEach(function(done) { + return db.docOps.insert({doc_id: ObjectId(this.doc_id), version: 1}, function(err) { + if (err != null) { return done(err); } + return DocstoreClient.destroyAllDoc(this.project_id, done); + }); + }); - it "should remove the doc from the docs collection", (done) -> - db.docs.find _id: @doc_id, (err, docs) -> - expect(err).not.to.exist - expect(docs).to.deep.equal [] - done() + it("should remove the doc from the docs collection", function(done) { + return db.docs.find({_id: this.doc_id}, function(err, docs) { + expect(err).not.to.exist; + expect(docs).to.deep.equal([]); + return done(); + }); + }); - it "should remove the docOps from the docOps collection", (done) -> - db.docOps.find doc_id: @doc_id, (err, docOps) -> - expect(err).not.to.exist - expect(docOps).to.deep.equal [] - done() + return it("should remove the docOps from the docOps collection", function(done) { + return db.docOps.find({doc_id: this.doc_id}, function(err, docOps) { + expect(err).not.to.exist; + expect(docOps).to.deep.equal([]); + return done(); + }); + }); + }); - describe "when the doc is archived", -> - beforeEach (done) -> - DocstoreClient.archiveAllDoc @project_id, (err) -> - return done(err) if err? - DocstoreClient.destroyAllDoc @project_id, done + return describe("when the doc is archived", function() { + beforeEach(function(done) { + return DocstoreClient.archiveAllDoc(this.project_id, function(err) { + if (err != null) { return done(err); } + return DocstoreClient.destroyAllDoc(this.project_id, done); + }); + }); - it "should remove the doc from the docs collection", (done) -> - db.docs.find _id: @doc_id, (err, docs) -> - expect(err).not.to.exist - expect(docs).to.deep.equal [] - done() + it("should remove the doc from the docs collection", function(done) { + return db.docs.find({_id: this.doc_id}, function(err, docs) { + expect(err).not.to.exist; + expect(docs).to.deep.equal([]); + return done(); + }); + }); - it "should remove the docOps from the docOps collection", (done) -> - db.docOps.find doc_id: @doc_id, (err, docOps) -> - expect(err).not.to.exist - expect(docOps).to.deep.equal [] - done() + it("should remove the docOps from the docOps collection", function(done) { + return db.docOps.find({doc_id: this.doc_id}, function(err, docOps) { + expect(err).not.to.exist; + expect(docOps).to.deep.equal([]); + return done(); + }); + }); - it "should remove the doc contents from s3", (done) -> - DocstoreClient.getS3Doc @project_id, @doc_id, (error, res, s3_doc) => - throw error if error? - expect(res.statusCode).to.equal 404 - done() + return it("should remove the doc contents from s3", function(done) { + return DocstoreClient.getS3Doc(this.project_id, this.doc_id, (error, res, s3_doc) => { + if (error != null) { throw error; } + expect(res.statusCode).to.equal(404); + return done(); + }); + }); + }); +}); diff --git a/services/docstore/test/acceptance/coffee/GettingAllDocsTests.js b/services/docstore/test/acceptance/coffee/GettingAllDocsTests.js index 6a16006044..e5df055760 100644 --- a/services/docstore/test/acceptance/coffee/GettingAllDocsTests.js +++ b/services/docstore/test/acceptance/coffee/GettingAllDocsTests.js @@ -1,63 +1,83 @@ -sinon = require "sinon" -chai = require("chai") -chai.should() -{ObjectId} = require "mongojs" -async = require "async" -DocstoreApp = require "./helpers/DocstoreApp" +/* + * decaffeinate suggestions: + * DS101: Remove unnecessary use of Array.from + * DS102: Remove unnecessary code created because of implicit returns + * DS207: Consider shorter variations of null checks + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +const sinon = require("sinon"); +const chai = require("chai"); +chai.should(); +const {ObjectId} = require("mongojs"); +const async = require("async"); +const DocstoreApp = require("./helpers/DocstoreApp"); -DocstoreClient = require "./helpers/DocstoreClient" +const DocstoreClient = require("./helpers/DocstoreClient"); -describe "Getting all docs", -> - beforeEach (done) -> - @project_id = ObjectId() - @docs = [{ - _id: ObjectId() - lines: ["one", "two", "three"] - ranges: {"mock": "one"} +describe("Getting all docs", function() { + beforeEach(function(done) { + this.project_id = ObjectId(); + this.docs = [{ + _id: ObjectId(), + lines: ["one", "two", "three"], + ranges: {"mock": "one"}, rev: 2 }, { - _id: ObjectId() - lines: ["aaa", "bbb", "ccc"] - ranges: {"mock": "two"} + _id: ObjectId(), + lines: ["aaa", "bbb", "ccc"], + ranges: {"mock": "two"}, rev: 4 }, { - _id: ObjectId() - lines: ["111", "222", "333"] - ranges: {"mock": "three"} + _id: ObjectId(), + lines: ["111", "222", "333"], + ranges: {"mock": "three"}, rev: 6 - }] - @deleted_doc = { - _id: ObjectId() - lines: ["deleted"] - ranges: {"mock": "four"} + }]; + this.deleted_doc = { + _id: ObjectId(), + lines: ["deleted"], + ranges: {"mock": "four"}, rev: 8 - } - version = 42 - jobs = for doc in @docs - do (doc) => - (callback) => - DocstoreClient.createDoc @project_id, doc._id, doc.lines, version, doc.ranges, callback - jobs.push (cb) => - DocstoreClient.createDoc @project_id, @deleted_doc._id, @deleted_doc.lines, version, @deleted_doc.ranges, (err)=> - DocstoreClient.deleteDoc @project_id, @deleted_doc._id, cb - jobs.unshift (cb)-> - DocstoreApp.ensureRunning cb - async.series jobs, done + }; + const version = 42; + const jobs = Array.from(this.docs).map((doc) => + (doc => { + return callback => { + return DocstoreClient.createDoc(this.project_id, doc._id, doc.lines, version, doc.ranges, callback); + }; + })(doc)); + jobs.push(cb => { + return DocstoreClient.createDoc(this.project_id, this.deleted_doc._id, this.deleted_doc.lines, version, this.deleted_doc.ranges, err=> { + return DocstoreClient.deleteDoc(this.project_id, this.deleted_doc._id, cb); + }); + }); + jobs.unshift(cb => DocstoreApp.ensureRunning(cb)); + return async.series(jobs, done); + }); - it "getAllDocs should return all the (non-deleted) docs", (done) -> - DocstoreClient.getAllDocs @project_id, (error, res, docs) => - throw error if error? - docs.length.should.equal @docs.length - for doc, i in docs - doc.lines.should.deep.equal @docs[i].lines - done() + it("getAllDocs should return all the (non-deleted) docs", function(done) { + return DocstoreClient.getAllDocs(this.project_id, (error, res, docs) => { + if (error != null) { throw error; } + docs.length.should.equal(this.docs.length); + for (let i = 0; i < docs.length; i++) { + const doc = docs[i]; + doc.lines.should.deep.equal(this.docs[i].lines); + } + return done(); + }); + }); - it "getAllRanges should return all the (non-deleted) doc ranges", (done) -> - DocstoreClient.getAllRanges @project_id, (error, res, docs) => - throw error if error? - docs.length.should.equal @docs.length - for doc, i in docs - doc.ranges.should.deep.equal @docs[i].ranges - done() + return it("getAllRanges should return all the (non-deleted) doc ranges", function(done) { + return DocstoreClient.getAllRanges(this.project_id, (error, res, docs) => { + if (error != null) { throw error; } + docs.length.should.equal(this.docs.length); + for (let i = 0; i < docs.length; i++) { + const doc = docs[i]; + doc.ranges.should.deep.equal(this.docs[i].ranges); + } + return done(); + }); + }); +}); diff --git a/services/docstore/test/acceptance/coffee/GettingDocsTests.js b/services/docstore/test/acceptance/coffee/GettingDocsTests.js index dbdbd31aa2..02c0b6d7b1 100644 --- a/services/docstore/test/acceptance/coffee/GettingDocsTests.js +++ b/services/docstore/test/acceptance/coffee/GettingDocsTests.js @@ -1,63 +1,83 @@ -sinon = require "sinon" -chai = require("chai") -chai.should() -{ObjectId} = require "mongojs" -DocstoreApp = require "./helpers/DocstoreApp" +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS207: Consider shorter variations of null checks + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +const sinon = require("sinon"); +const chai = require("chai"); +chai.should(); +const {ObjectId} = require("mongojs"); +const DocstoreApp = require("./helpers/DocstoreApp"); -DocstoreClient = require "./helpers/DocstoreClient" +const DocstoreClient = require("./helpers/DocstoreClient"); -describe "Getting a doc", -> - beforeEach (done) -> - @project_id = ObjectId() - @doc_id = ObjectId() - @lines = ["original", "lines"] - @version = 42 - @ranges = { +describe("Getting a doc", function() { + beforeEach(function(done) { + this.project_id = ObjectId(); + this.doc_id = ObjectId(); + this.lines = ["original", "lines"]; + this.version = 42; + this.ranges = { changes: [{ - id: ObjectId().toString() - op: { i: "foo", p: 3 } - meta: - user_id: ObjectId().toString() + id: ObjectId().toString(), + op: { i: "foo", p: 3 }, + meta: { + user_id: ObjectId().toString(), ts: new Date().toString() + } }] - } - DocstoreApp.ensureRunning => - DocstoreClient.createDoc @project_id, @doc_id, @lines, @version, @ranges, (error) => - throw error if error? - done() + }; + return DocstoreApp.ensureRunning(() => { + return DocstoreClient.createDoc(this.project_id, this.doc_id, this.lines, this.version, this.ranges, error => { + if (error != null) { throw error; } + return done(); + }); + }); + }); - describe "when the doc exists", -> - it "should get the doc lines and version", (done) -> - DocstoreClient.getDoc @project_id, @doc_id, {}, (error, res, doc) => - doc.lines.should.deep.equal @lines - doc.version.should.equal @version - doc.ranges.should.deep.equal @ranges - done() + describe("when the doc exists", () => it("should get the doc lines and version", function(done) { + return DocstoreClient.getDoc(this.project_id, this.doc_id, {}, (error, res, doc) => { + doc.lines.should.deep.equal(this.lines); + doc.version.should.equal(this.version); + doc.ranges.should.deep.equal(this.ranges); + return done(); + }); + })); - describe "when the doc does not exist", -> - it "should return a 404", (done) -> - missing_doc_id = ObjectId() - DocstoreClient.getDoc @project_id, missing_doc_id, {}, (error, res, doc) -> - res.statusCode.should.equal 404 - done() + describe("when the doc does not exist", () => it("should return a 404", function(done) { + const missing_doc_id = ObjectId(); + return DocstoreClient.getDoc(this.project_id, missing_doc_id, {}, function(error, res, doc) { + res.statusCode.should.equal(404); + return done(); + }); + })); - describe "when the doc is a deleted doc", -> - beforeEach (done) -> - @deleted_doc_id = ObjectId() - DocstoreClient.createDoc @project_id, @deleted_doc_id, @lines, @version, @ranges, (error) => - throw error if error? - DocstoreClient.deleteDoc @project_id, @deleted_doc_id, done + return describe("when the doc is a deleted doc", function() { + beforeEach(function(done) { + this.deleted_doc_id = ObjectId(); + return DocstoreClient.createDoc(this.project_id, this.deleted_doc_id, this.lines, this.version, this.ranges, error => { + if (error != null) { throw error; } + return DocstoreClient.deleteDoc(this.project_id, this.deleted_doc_id, done); + }); + }); - it "should return the doc", (done) -> - DocstoreClient.getDoc @project_id, @deleted_doc_id, {include_deleted:true},(error, res, doc) => - doc.lines.should.deep.equal @lines - doc.version.should.equal @version - doc.ranges.should.deep.equal @ranges - doc.deleted.should.equal true - done() + it("should return the doc", function(done) { + return DocstoreClient.getDoc(this.project_id, this.deleted_doc_id, {include_deleted:true},(error, res, doc) => { + doc.lines.should.deep.equal(this.lines); + doc.version.should.equal(this.version); + doc.ranges.should.deep.equal(this.ranges); + doc.deleted.should.equal(true); + return done(); + }); + }); - it "should return a 404 when the query string is not set", (done)-> - DocstoreClient.getDoc @project_id, @deleted_doc_id, {},(error, res, doc) => - res.statusCode.should.equal 404 - done() + return it("should return a 404 when the query string is not set", function(done){ + return DocstoreClient.getDoc(this.project_id, this.deleted_doc_id, {},(error, res, doc) => { + res.statusCode.should.equal(404); + return done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/services/docstore/test/acceptance/coffee/UpdatingDocsTests.js b/services/docstore/test/acceptance/coffee/UpdatingDocsTests.js index 2b916a3a83..b5f12af3c8 100644 --- a/services/docstore/test/acceptance/coffee/UpdatingDocsTests.js +++ b/services/docstore/test/acceptance/coffee/UpdatingDocsTests.js @@ -1,225 +1,332 @@ -sinon = require "sinon" -chai = require("chai") -chai.should() -{ObjectId} = require "mongojs" -DocstoreApp = require "./helpers/DocstoreApp" +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS207: Consider shorter variations of null checks + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +const sinon = require("sinon"); +const chai = require("chai"); +chai.should(); +const {ObjectId} = require("mongojs"); +const DocstoreApp = require("./helpers/DocstoreApp"); -DocstoreClient = require "./helpers/DocstoreClient" +const DocstoreClient = require("./helpers/DocstoreClient"); -describe "Applying updates to a doc", -> - beforeEach (done) -> - @project_id = ObjectId() - @doc_id = ObjectId() - @originalLines = ["original", "lines"] - @newLines = ["new", "lines"] - @originalRanges = { +describe("Applying updates to a doc", function() { + beforeEach(function(done) { + this.project_id = ObjectId(); + this.doc_id = ObjectId(); + this.originalLines = ["original", "lines"]; + this.newLines = ["new", "lines"]; + this.originalRanges = { changes: [{ - id: ObjectId().toString() - op: { i: "foo", p: 3 } - meta: - user_id: ObjectId().toString() + id: ObjectId().toString(), + op: { i: "foo", p: 3 }, + meta: { + user_id: ObjectId().toString(), ts: new Date().toString() + } }] - } - @newRanges = { + }; + this.newRanges = { changes: [{ - id: ObjectId().toString() - op: { i: "bar", p: 6 } - meta: - user_id: ObjectId().toString() + id: ObjectId().toString(), + op: { i: "bar", p: 6 }, + meta: { + user_id: ObjectId().toString(), ts: new Date().toString() + } }] - } - @version = 42 - DocstoreApp.ensureRunning => - DocstoreClient.createDoc @project_id, @doc_id, @originalLines, @version, @originalRanges, (error) => - throw error if error? - done() + }; + this.version = 42; + return DocstoreApp.ensureRunning(() => { + return DocstoreClient.createDoc(this.project_id, this.doc_id, this.originalLines, this.version, this.originalRanges, error => { + if (error != null) { throw error; } + return done(); + }); + }); + }); - describe "when nothing has been updated", -> - beforeEach (done) -> - DocstoreClient.updateDoc @project_id, @doc_id, @originalLines, @version, @originalRanges, (error, res, @body) => - done() + describe("when nothing has been updated", function() { + beforeEach(function(done) { + return DocstoreClient.updateDoc(this.project_id, this.doc_id, this.originalLines, this.version, this.originalRanges, (error, res, body) => { + this.body = body; + return done(); + }); + }); - it "should return modified = false", -> - @body.modified.should.equal false + it("should return modified = false", function() { + return this.body.modified.should.equal(false); + }); - it "should not update the doc in the API", (done) -> - DocstoreClient.getDoc @project_id, @doc_id, {}, (error, res, doc) => - doc.lines.should.deep.equal @originalLines - doc.version.should.equal @version - doc.ranges.should.deep.equal @originalRanges - done() + return it("should not update the doc in the API", function(done) { + return DocstoreClient.getDoc(this.project_id, this.doc_id, {}, (error, res, doc) => { + doc.lines.should.deep.equal(this.originalLines); + doc.version.should.equal(this.version); + doc.ranges.should.deep.equal(this.originalRanges); + return done(); + }); + }); + }); - describe "when the lines have changed", -> - beforeEach (done) -> - DocstoreClient.updateDoc @project_id, @doc_id, @newLines, @version, @originalRanges, (error, res, @body) => - done() + describe("when the lines have changed", function() { + beforeEach(function(done) { + return DocstoreClient.updateDoc(this.project_id, this.doc_id, this.newLines, this.version, this.originalRanges, (error, res, body) => { + this.body = body; + return done(); + }); + }); - it "should return modified = true", -> - @body.modified.should.equal true + it("should return modified = true", function() { + return this.body.modified.should.equal(true); + }); - it "should return the rev", -> - @body.rev.should.equal 2 + it("should return the rev", function() { + return this.body.rev.should.equal(2); + }); - it "should update the doc in the API", (done) -> - DocstoreClient.getDoc @project_id, @doc_id, {}, (error, res, doc) => - doc.lines.should.deep.equal @newLines - doc.version.should.equal @version - doc.ranges.should.deep.equal @originalRanges - done() + return it("should update the doc in the API", function(done) { + return DocstoreClient.getDoc(this.project_id, this.doc_id, {}, (error, res, doc) => { + doc.lines.should.deep.equal(this.newLines); + doc.version.should.equal(this.version); + doc.ranges.should.deep.equal(this.originalRanges); + return done(); + }); + }); + }); - describe "when the version has changed", -> - beforeEach (done) -> - DocstoreClient.updateDoc @project_id, @doc_id, @originalLines, @version + 1, @originalRanges, (error, res, @body) => - done() + describe("when the version has changed", function() { + beforeEach(function(done) { + return DocstoreClient.updateDoc(this.project_id, this.doc_id, this.originalLines, this.version + 1, this.originalRanges, (error, res, body) => { + this.body = body; + return done(); + }); + }); - it "should return modified = true", -> - @body.modified.should.equal true + it("should return modified = true", function() { + return this.body.modified.should.equal(true); + }); - it "should return the rev", -> - @body.rev.should.equal 1 + it("should return the rev", function() { + return this.body.rev.should.equal(1); + }); - it "should update the doc in the API", (done) -> - DocstoreClient.getDoc @project_id, @doc_id, {}, (error, res, doc) => - doc.lines.should.deep.equal @originalLines - doc.version.should.equal @version + 1 - doc.ranges.should.deep.equal @originalRanges - done() + return it("should update the doc in the API", function(done) { + return DocstoreClient.getDoc(this.project_id, this.doc_id, {}, (error, res, doc) => { + doc.lines.should.deep.equal(this.originalLines); + doc.version.should.equal(this.version + 1); + doc.ranges.should.deep.equal(this.originalRanges); + return done(); + }); + }); + }); - describe "when the ranges have changed", -> - beforeEach (done) -> - DocstoreClient.updateDoc @project_id, @doc_id, @originalLines, @version, @newRanges, (error, res, @body) => - done() + describe("when the ranges have changed", function() { + beforeEach(function(done) { + return DocstoreClient.updateDoc(this.project_id, this.doc_id, this.originalLines, this.version, this.newRanges, (error, res, body) => { + this.body = body; + return done(); + }); + }); - it "should return modified = true", -> - @body.modified.should.equal true + it("should return modified = true", function() { + return this.body.modified.should.equal(true); + }); - it "should return the rev", -> - @body.rev.should.equal 2 + it("should return the rev", function() { + return this.body.rev.should.equal(2); + }); - it "should update the doc in the API", (done) -> - DocstoreClient.getDoc @project_id, @doc_id, {}, (error, res, doc) => - doc.lines.should.deep.equal @originalLines - doc.version.should.equal @version - doc.ranges.should.deep.equal @newRanges - done() + return it("should update the doc in the API", function(done) { + return DocstoreClient.getDoc(this.project_id, this.doc_id, {}, (error, res, doc) => { + doc.lines.should.deep.equal(this.originalLines); + doc.version.should.equal(this.version); + doc.ranges.should.deep.equal(this.newRanges); + return done(); + }); + }); + }); - describe "when the doc does not exist", -> - beforeEach (done) -> - @missing_doc_id = ObjectId() - DocstoreClient.updateDoc @project_id, @missing_doc_id, @originalLines, 0, @originalRanges, (error, @res, @body) => - done() + describe("when the doc does not exist", function() { + beforeEach(function(done) { + this.missing_doc_id = ObjectId(); + return DocstoreClient.updateDoc(this.project_id, this.missing_doc_id, this.originalLines, 0, this.originalRanges, (error, res, body) => { + this.res = res; + this.body = body; + return done(); + }); + }); - it "should create the doc", -> - @body.rev.should.equal 1 + it("should create the doc", function() { + return this.body.rev.should.equal(1); + }); - it "should be retreivable", (done)-> - DocstoreClient.getDoc @project_id, @missing_doc_id, {}, (error, res, doc) => - doc.lines.should.deep.equal @originalLines - doc.version.should.equal 0 - doc.ranges.should.deep.equal @originalRanges - done() + return it("should be retreivable", function(done){ + return DocstoreClient.getDoc(this.project_id, this.missing_doc_id, {}, (error, res, doc) => { + doc.lines.should.deep.equal(this.originalLines); + doc.version.should.equal(0); + doc.ranges.should.deep.equal(this.originalRanges); + return done(); + }); + }); + }); - describe "when malformed doc lines are provided", -> - describe "when the lines are not an array", -> - beforeEach (done) -> - DocstoreClient.updateDoc @project_id, @doc_id, { foo: "bar" }, @version, @originalRanges, (error, @res, @body) => - done() + describe("when malformed doc lines are provided", function() { + describe("when the lines are not an array", function() { + beforeEach(function(done) { + return DocstoreClient.updateDoc(this.project_id, this.doc_id, { foo: "bar" }, this.version, this.originalRanges, (error, res, body) => { + this.res = res; + this.body = body; + return done(); + }); + }); - it "should return 400", -> - @res.statusCode.should.equal 400 + it("should return 400", function() { + return this.res.statusCode.should.equal(400); + }); - it "should not update the doc in the API", (done) -> - DocstoreClient.getDoc @project_id, @doc_id, {}, (error, res, doc) => - doc.lines.should.deep.equal @originalLines - done() + return it("should not update the doc in the API", function(done) { + return DocstoreClient.getDoc(this.project_id, this.doc_id, {}, (error, res, doc) => { + doc.lines.should.deep.equal(this.originalLines); + return done(); + }); + }); + }); - describe "when the lines are not present", -> - beforeEach (done) -> - DocstoreClient.updateDoc @project_id, @doc_id, null, @version, @originalRanges, (error, @res, @body) => - done() + return describe("when the lines are not present", function() { + beforeEach(function(done) { + return DocstoreClient.updateDoc(this.project_id, this.doc_id, null, this.version, this.originalRanges, (error, res, body) => { + this.res = res; + this.body = body; + return done(); + }); + }); - it "should return 400", -> - @res.statusCode.should.equal 400 + it("should return 400", function() { + return this.res.statusCode.should.equal(400); + }); - it "should not update the doc in the API", (done) -> - DocstoreClient.getDoc @project_id, @doc_id, {}, (error, res, doc) => - doc.lines.should.deep.equal @originalLines - done() + return it("should not update the doc in the API", function(done) { + return DocstoreClient.getDoc(this.project_id, this.doc_id, {}, (error, res, doc) => { + doc.lines.should.deep.equal(this.originalLines); + return done(); + }); + }); + }); + }); - describe "when no version is provided", -> - beforeEach (done) -> - DocstoreClient.updateDoc @project_id, @doc_id, @originalLines, null, @originalRanges, (error, @res, @body) => - done() + describe("when no version is provided", function() { + beforeEach(function(done) { + return DocstoreClient.updateDoc(this.project_id, this.doc_id, this.originalLines, null, this.originalRanges, (error, res, body) => { + this.res = res; + this.body = body; + return done(); + }); + }); - it "should return 400", -> - @res.statusCode.should.equal 400 + it("should return 400", function() { + return this.res.statusCode.should.equal(400); + }); - it "should not update the doc in the API", (done) -> - DocstoreClient.getDoc @project_id, @doc_id, {}, (error, res, doc) => - doc.lines.should.deep.equal @originalLines - doc.version.should.equal @version - done() + return it("should not update the doc in the API", function(done) { + return DocstoreClient.getDoc(this.project_id, this.doc_id, {}, (error, res, doc) => { + doc.lines.should.deep.equal(this.originalLines); + doc.version.should.equal(this.version); + return done(); + }); + }); + }); - describe "when the content is large", -> - beforeEach (done) -> - line = new Array(1025).join("x") # 1kb - @largeLines = Array.apply(null, Array(1024)).map(() -> line) # 1mb - DocstoreClient.updateDoc @project_id, @doc_id, @largeLines, @version, @originalRanges, (error, res, @body) => - done() + describe("when the content is large", function() { + beforeEach(function(done) { + const line = new Array(1025).join("x"); // 1kb + this.largeLines = Array.apply(null, Array(1024)).map(() => line); // 1mb + return DocstoreClient.updateDoc(this.project_id, this.doc_id, this.largeLines, this.version, this.originalRanges, (error, res, body) => { + this.body = body; + return done(); + }); + }); - it "should return modified = true", -> - @body.modified.should.equal true + it("should return modified = true", function() { + return this.body.modified.should.equal(true); + }); - it "should update the doc in the API", (done) -> - DocstoreClient.getDoc @project_id, @doc_id, {}, (error, res, doc) => - doc.lines.should.deep.equal @largeLines - done() + return it("should update the doc in the API", function(done) { + return DocstoreClient.getDoc(this.project_id, this.doc_id, {}, (error, res, doc) => { + doc.lines.should.deep.equal(this.largeLines); + return done(); + }); + }); + }); - describe "when there is a large json payload", -> - beforeEach (done) -> - line = new Array(1025).join("x") # 1kb - @largeLines = Array.apply(null, Array(1024)).map(() -> line) # 1kb - @originalRanges.padding = Array.apply(null, Array(2049)).map(() -> line) # 2mb + 1kb - DocstoreClient.updateDoc @project_id, @doc_id, @largeLines, @version, @originalRanges, (error, @res, @body) => - done() + describe("when there is a large json payload", function() { + beforeEach(function(done) { + const line = new Array(1025).join("x"); // 1kb + this.largeLines = Array.apply(null, Array(1024)).map(() => line); // 1kb + this.originalRanges.padding = Array.apply(null, Array(2049)).map(() => line); // 2mb + 1kb + return DocstoreClient.updateDoc(this.project_id, this.doc_id, this.largeLines, this.version, this.originalRanges, (error, res, body) => { + this.res = res; + this.body = body; + return done(); + }); + }); - it "should return modified = true", -> - @body.modified.should.equal true + it("should return modified = true", function() { + return this.body.modified.should.equal(true); + }); - it "should update the doc in the API", (done) -> - DocstoreClient.getDoc @project_id, @doc_id, {}, (error, res, doc) => - doc.lines.should.deep.equal @largeLines - done() + return it("should update the doc in the API", function(done) { + return DocstoreClient.getDoc(this.project_id, this.doc_id, {}, (error, res, doc) => { + doc.lines.should.deep.equal(this.largeLines); + return done(); + }); + }); + }); - describe "when the document body is too large", -> - beforeEach (done) -> - line = new Array(1025).join("x") # 1kb - @largeLines = Array.apply(null, Array(2049)).map(() -> line) # 2mb + 1kb - DocstoreClient.updateDoc @project_id, @doc_id, @largeLines, @version, @originalRanges, (error, @res, @body) => - done() + describe("when the document body is too large", function() { + beforeEach(function(done) { + const line = new Array(1025).join("x"); // 1kb + this.largeLines = Array.apply(null, Array(2049)).map(() => line); // 2mb + 1kb + return DocstoreClient.updateDoc(this.project_id, this.doc_id, this.largeLines, this.version, this.originalRanges, (error, res, body) => { + this.res = res; + this.body = body; + return done(); + }); + }); - it "should return 413", -> - @res.statusCode.should.equal 413 + it("should return 413", function() { + return this.res.statusCode.should.equal(413); + }); - it "should report body too large", -> - @res.body.should.equal 'document body too large' + it("should report body too large", function() { + return this.res.body.should.equal('document body too large'); + }); - it "should not update the doc in the API", (done) -> - DocstoreClient.getDoc @project_id, @doc_id, {}, (error, res, doc) => - doc.lines.should.deep.equal @originalLines - done() + return it("should not update the doc in the API", function(done) { + return DocstoreClient.getDoc(this.project_id, this.doc_id, {}, (error, res, doc) => { + doc.lines.should.deep.equal(this.originalLines); + return done(); + }); + }); + }); - describe "when the json payload is too large", -> - beforeEach (done) -> - line = new Array(1025).join("x") # 1kb - @largeLines = Array.apply(null, Array(1024)).map(() -> line) # 1kb - @originalRanges.padding = Array.apply(null, Array(4096)).map(() -> line) # 4mb - DocstoreClient.updateDoc @project_id, @doc_id, @largeLines, @version, @originalRanges, (error, @res, @body) => - done() + return describe("when the json payload is too large", function() { + beforeEach(function(done) { + const line = new Array(1025).join("x"); // 1kb + this.largeLines = Array.apply(null, Array(1024)).map(() => line); // 1kb + this.originalRanges.padding = Array.apply(null, Array(4096)).map(() => line); // 4mb + return DocstoreClient.updateDoc(this.project_id, this.doc_id, this.largeLines, this.version, this.originalRanges, (error, res, body) => { + this.res = res; + this.body = body; + return done(); + }); + }); - it "should not update the doc in the API", (done) -> - DocstoreClient.getDoc @project_id, @doc_id, {}, (error, res, doc) => - doc.lines.should.deep.equal @originalLines - done() + return it("should not update the doc in the API", function(done) { + return DocstoreClient.getDoc(this.project_id, this.doc_id, {}, (error, res, doc) => { + doc.lines.should.deep.equal(this.originalLines); + return done(); + }); + }); + }); +}); diff --git a/services/docstore/test/acceptance/coffee/helpers/DocstoreApp.js b/services/docstore/test/acceptance/coffee/helpers/DocstoreApp.js index 4a916955a9..533284d8a3 100644 --- a/services/docstore/test/acceptance/coffee/helpers/DocstoreApp.js +++ b/services/docstore/test/acceptance/coffee/helpers/DocstoreApp.js @@ -1,21 +1,39 @@ -app = require('../../../../app') -require("logger-sharelatex").logger.level("error") -settings = require("settings-sharelatex") +/* + * decaffeinate suggestions: + * DS101: Remove unnecessary use of Array.from + * DS102: Remove unnecessary code created because of implicit returns + * DS205: Consider reworking code to avoid use of IIFEs + * DS207: Consider shorter variations of null checks + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +const app = require('../../../../app'); +require("logger-sharelatex").logger.level("error"); +const settings = require("settings-sharelatex"); -module.exports = - running: false - initing: false - callbacks: [] - ensureRunning: (callback = (error) ->) -> - if @running - return callback() - else if @initing - @callbacks.push callback - else - @initing = true - @callbacks.push callback - app.listen settings.internal.docstore.port, "localhost", (error) => - throw error if error? - @running = true - for callback in @callbacks - callback() \ No newline at end of file +module.exports = { + running: false, + initing: false, + callbacks: [], + ensureRunning(callback) { + if (callback == null) { callback = function(error) {}; } + if (this.running) { + return callback(); + } else if (this.initing) { + return this.callbacks.push(callback); + } else { + this.initing = true; + this.callbacks.push(callback); + return app.listen(settings.internal.docstore.port, "localhost", error => { + if (error != null) { throw error; } + this.running = true; + return (() => { + const result = []; + for (callback of Array.from(this.callbacks)) { + result.push(callback()); + } + return result; + })(); + }); + } + } +}; \ No newline at end of file diff --git a/services/docstore/test/acceptance/coffee/helpers/DocstoreClient.js b/services/docstore/test/acceptance/coffee/helpers/DocstoreClient.js index 446f99ad58..61cc519ec6 100644 --- a/services/docstore/test/acceptance/coffee/helpers/DocstoreClient.js +++ b/services/docstore/test/acceptance/coffee/helpers/DocstoreClient.js @@ -1,57 +1,84 @@ -request = require("request").defaults(jar: false) -{db, ObjectId} = require("../../../../app/js/mongojs") -settings = require("settings-sharelatex") -DocArchiveManager = require("../../../../app/js/DocArchiveManager.js") +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS207: Consider shorter variations of null checks + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +let DocstoreClient; +const request = require("request").defaults({jar: false}); +const {db, ObjectId} = require("../../../../app/js/mongojs"); +const settings = require("settings-sharelatex"); +const DocArchiveManager = require("../../../../app/js/DocArchiveManager.js"); -module.exports = DocstoreClient = +module.exports = (DocstoreClient = { - createDoc: (project_id, doc_id, lines, version, ranges, callback = (error) ->) -> - DocstoreClient.updateDoc project_id, doc_id, lines, version, ranges, callback + createDoc(project_id, doc_id, lines, version, ranges, callback) { + if (callback == null) { callback = function(error) {}; } + return DocstoreClient.updateDoc(project_id, doc_id, lines, version, ranges, callback); + }, - getDoc: (project_id, doc_id, qs, callback = (error, res, body) ->) -> - request.get { - url: "http://localhost:#{settings.internal.docstore.port}/project/#{project_id}/doc/#{doc_id}" + getDoc(project_id, doc_id, qs, callback) { + if (callback == null) { callback = function(error, res, body) {}; } + return request.get({ + url: `http://localhost:${settings.internal.docstore.port}/project/${project_id}/doc/${doc_id}`, + json: true, + qs + }, callback); + }, + + getAllDocs(project_id, callback) { + if (callback == null) { callback = function(error, res, body) {}; } + return request.get({ + url: `http://localhost:${settings.internal.docstore.port}/project/${project_id}/doc`, json: true - qs:qs - }, callback + }, callback); + }, - getAllDocs: (project_id, callback = (error, res, body) ->) -> - request.get { - url: "http://localhost:#{settings.internal.docstore.port}/project/#{project_id}/doc" + getAllRanges(project_id, callback) { + if (callback == null) { callback = function(error, res, body) {}; } + return request.get({ + url: `http://localhost:${settings.internal.docstore.port}/project/${project_id}/ranges`, json: true - }, callback + }, callback); + }, - getAllRanges: (project_id, callback = (error, res, body) ->) -> - request.get { - url: "http://localhost:#{settings.internal.docstore.port}/project/#{project_id}/ranges" - json: true - }, callback + updateDoc(project_id, doc_id, lines, version, ranges, callback) { + if (callback == null) { callback = function(error, res, body) {}; } + return request.post({ + url: `http://localhost:${settings.internal.docstore.port}/project/${project_id}/doc/${doc_id}`, + json: { + lines, + version, + ranges + } + }, callback); + }, - updateDoc: (project_id, doc_id, lines, version, ranges, callback = (error, res, body) ->) -> - request.post { - url: "http://localhost:#{settings.internal.docstore.port}/project/#{project_id}/doc/#{doc_id}" - json: - lines: lines - version: version - ranges: ranges - }, callback - - deleteDoc: (project_id, doc_id, callback = (error, res, body) ->) -> - request.del { - url: "http://localhost:#{settings.internal.docstore.port}/project/#{project_id}/doc/#{doc_id}" - }, callback + deleteDoc(project_id, doc_id, callback) { + if (callback == null) { callback = function(error, res, body) {}; } + return request.del({ + url: `http://localhost:${settings.internal.docstore.port}/project/${project_id}/doc/${doc_id}` + }, callback); + }, - archiveAllDoc: (project_id, callback = (error, res, body) ->) -> - request.post { - url: "http://localhost:#{settings.internal.docstore.port}/project/#{project_id}/archive" - }, callback + archiveAllDoc(project_id, callback) { + if (callback == null) { callback = function(error, res, body) {}; } + return request.post({ + url: `http://localhost:${settings.internal.docstore.port}/project/${project_id}/archive` + }, callback); + }, - destroyAllDoc: (project_id, callback = (error, res, body) ->) -> - request.post { - url: "http://localhost:#{settings.internal.docstore.port}/project/#{project_id}/destroy" - }, callback + destroyAllDoc(project_id, callback) { + if (callback == null) { callback = function(error, res, body) {}; } + return request.post({ + url: `http://localhost:${settings.internal.docstore.port}/project/${project_id}/destroy` + }, callback); + }, - getS3Doc: (project_id, doc_id, callback = (error, res, body) ->) -> - options = DocArchiveManager.buildS3Options(project_id+"/"+doc_id) - options.json = true - request.get options, callback + getS3Doc(project_id, doc_id, callback) { + if (callback == null) { callback = function(error, res, body) {}; } + const options = DocArchiveManager.buildS3Options(project_id+"/"+doc_id); + options.json = true; + return request.get(options, callback); + } +}); From 1391ae96e7b73da9ff85d7b76b13519d4c2d2e1d Mon Sep 17 00:00:00 2001 From: decaffeinate <s@sd.ai> Date: Sun, 16 Feb 2020 14:03:03 +0000 Subject: [PATCH 16/27] decaffeinate: Run post-processing cleanups on ArchiveDocsTests.coffee and 6 other files --- .../acceptance/coffee/ArchiveDocsTests.js | 9 +++++++- .../acceptance/coffee/DeletingDocsTests.js | 21 ++++++++++++------- .../acceptance/coffee/GettingAllDocsTests.js | 6 ++++++ .../acceptance/coffee/GettingDocsTests.js | 17 ++++++++++----- .../acceptance/coffee/UpdatingDocsTests.js | 6 ++++++ .../acceptance/coffee/helpers/DocstoreApp.js | 5 +++++ .../coffee/helpers/DocstoreClient.js | 7 +++++++ 7 files changed, 58 insertions(+), 13 deletions(-) diff --git a/services/docstore/test/acceptance/coffee/ArchiveDocsTests.js b/services/docstore/test/acceptance/coffee/ArchiveDocsTests.js index ac3a14f637..69a3ec2308 100644 --- a/services/docstore/test/acceptance/coffee/ArchiveDocsTests.js +++ b/services/docstore/test/acceptance/coffee/ArchiveDocsTests.js @@ -1,3 +1,10 @@ +/* eslint-disable + camelcase, + handle-callback-err, + no-unused-vars, +*/ +// TODO: This file was created by bulk-decaffeinate. +// Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS101: Remove unnecessary use of Array.from @@ -19,7 +26,7 @@ const DocstoreClient = require("./helpers/DocstoreClient"); describe("Archiving", function() { - before(done => DocstoreApp.ensureRunning(done)); + before(function(done) { return DocstoreApp.ensureRunning(done); }); describe("multiple docs in a project", function() { before(function(done) { diff --git a/services/docstore/test/acceptance/coffee/DeletingDocsTests.js b/services/docstore/test/acceptance/coffee/DeletingDocsTests.js index 3fd2bf240d..026730205d 100644 --- a/services/docstore/test/acceptance/coffee/DeletingDocsTests.js +++ b/services/docstore/test/acceptance/coffee/DeletingDocsTests.js @@ -1,3 +1,10 @@ +/* eslint-disable + camelcase, + handle-callback-err, + no-unused-vars, +*/ +// TODO: This file was created by bulk-decaffeinate. +// Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS102: Remove unnecessary code created because of implicit returns @@ -52,13 +59,13 @@ describe("Deleting a doc", function() { }); }); - return describe("when the doc does not exist", () => it("should return a 404", function(done) { + return describe("when the doc does not exist", function() { return it("should return a 404", function(done) { const missing_doc_id = ObjectId(); - return DocstoreClient.deleteDoc(this.project_id, missing_doc_id, function(error, res, doc) { + return DocstoreClient.deleteDoc(this.project_id, missing_doc_id, (error, res, doc) => { res.statusCode.should.equal(404); return done(); }); - })); + }); }); }); describe("Destroying a project's documents", function() { @@ -71,7 +78,7 @@ describe("Destroying a project's documents", function() { }); it("should remove the doc from the docs collection", function(done) { - return db.docs.find({_id: this.doc_id}, function(err, docs) { + return db.docs.find({_id: this.doc_id}, (err, docs) => { expect(err).not.to.exist; expect(docs).to.deep.equal([]); return done(); @@ -79,7 +86,7 @@ describe("Destroying a project's documents", function() { }); return it("should remove the docOps from the docOps collection", function(done) { - return db.docOps.find({doc_id: this.doc_id}, function(err, docOps) { + return db.docOps.find({doc_id: this.doc_id}, (err, docOps) => { expect(err).not.to.exist; expect(docOps).to.deep.equal([]); return done(); @@ -96,7 +103,7 @@ describe("Destroying a project's documents", function() { }); it("should remove the doc from the docs collection", function(done) { - return db.docs.find({_id: this.doc_id}, function(err, docs) { + return db.docs.find({_id: this.doc_id}, (err, docs) => { expect(err).not.to.exist; expect(docs).to.deep.equal([]); return done(); @@ -104,7 +111,7 @@ describe("Destroying a project's documents", function() { }); it("should remove the docOps from the docOps collection", function(done) { - return db.docOps.find({doc_id: this.doc_id}, function(err, docOps) { + return db.docOps.find({doc_id: this.doc_id}, (err, docOps) => { expect(err).not.to.exist; expect(docOps).to.deep.equal([]); return done(); diff --git a/services/docstore/test/acceptance/coffee/GettingAllDocsTests.js b/services/docstore/test/acceptance/coffee/GettingAllDocsTests.js index e5df055760..2970042480 100644 --- a/services/docstore/test/acceptance/coffee/GettingAllDocsTests.js +++ b/services/docstore/test/acceptance/coffee/GettingAllDocsTests.js @@ -1,3 +1,9 @@ +/* eslint-disable + handle-callback-err, + no-unused-vars, +*/ +// TODO: This file was created by bulk-decaffeinate. +// Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS101: Remove unnecessary use of Array.from diff --git a/services/docstore/test/acceptance/coffee/GettingDocsTests.js b/services/docstore/test/acceptance/coffee/GettingDocsTests.js index 02c0b6d7b1..e6a96d0958 100644 --- a/services/docstore/test/acceptance/coffee/GettingDocsTests.js +++ b/services/docstore/test/acceptance/coffee/GettingDocsTests.js @@ -1,3 +1,10 @@ +/* eslint-disable + camelcase, + handle-callback-err, + no-unused-vars, +*/ +// TODO: This file was created by bulk-decaffeinate. +// Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS102: Remove unnecessary code created because of implicit returns @@ -36,22 +43,22 @@ describe("Getting a doc", function() { }); }); - describe("when the doc exists", () => it("should get the doc lines and version", function(done) { + describe("when the doc exists", function() { return it("should get the doc lines and version", function(done) { return DocstoreClient.getDoc(this.project_id, this.doc_id, {}, (error, res, doc) => { doc.lines.should.deep.equal(this.lines); doc.version.should.equal(this.version); doc.ranges.should.deep.equal(this.ranges); return done(); }); - })); + }); }); - describe("when the doc does not exist", () => it("should return a 404", function(done) { + describe("when the doc does not exist", function() { return it("should return a 404", function(done) { const missing_doc_id = ObjectId(); - return DocstoreClient.getDoc(this.project_id, missing_doc_id, {}, function(error, res, doc) { + return DocstoreClient.getDoc(this.project_id, missing_doc_id, {}, (error, res, doc) => { res.statusCode.should.equal(404); return done(); }); - })); + }); }); return describe("when the doc is a deleted doc", function() { beforeEach(function(done) { diff --git a/services/docstore/test/acceptance/coffee/UpdatingDocsTests.js b/services/docstore/test/acceptance/coffee/UpdatingDocsTests.js index b5f12af3c8..b3908ba2c4 100644 --- a/services/docstore/test/acceptance/coffee/UpdatingDocsTests.js +++ b/services/docstore/test/acceptance/coffee/UpdatingDocsTests.js @@ -1,3 +1,9 @@ +/* eslint-disable + handle-callback-err, + no-unused-vars, +*/ +// TODO: This file was created by bulk-decaffeinate. +// Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS102: Remove unnecessary code created because of implicit returns diff --git a/services/docstore/test/acceptance/coffee/helpers/DocstoreApp.js b/services/docstore/test/acceptance/coffee/helpers/DocstoreApp.js index 533284d8a3..9fd8389576 100644 --- a/services/docstore/test/acceptance/coffee/helpers/DocstoreApp.js +++ b/services/docstore/test/acceptance/coffee/helpers/DocstoreApp.js @@ -1,3 +1,8 @@ +/* eslint-disable + handle-callback-err, +*/ +// TODO: This file was created by bulk-decaffeinate. +// Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS101: Remove unnecessary use of Array.from diff --git a/services/docstore/test/acceptance/coffee/helpers/DocstoreClient.js b/services/docstore/test/acceptance/coffee/helpers/DocstoreClient.js index 61cc519ec6..129723a9ea 100644 --- a/services/docstore/test/acceptance/coffee/helpers/DocstoreClient.js +++ b/services/docstore/test/acceptance/coffee/helpers/DocstoreClient.js @@ -1,3 +1,10 @@ +/* eslint-disable + camelcase, + handle-callback-err, + no-unused-vars, +*/ +// TODO: This file was created by bulk-decaffeinate. +// Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS102: Remove unnecessary code created because of implicit returns From 7e131e4c71743aed6e1f9c1bb7a700c5f6eb9c9b Mon Sep 17 00:00:00 2001 From: Simon Detheridge <s@sd.ai> Date: Sun, 16 Feb 2020 14:03:06 +0000 Subject: [PATCH 17/27] decaffeinate: rename test/acceptance/coffee to test/acceptance/js --- .../docstore/test/acceptance/{coffee => js}/ArchiveDocsTests.js | 0 .../docstore/test/acceptance/{coffee => js}/DeletingDocsTests.js | 0 .../test/acceptance/{coffee => js}/GettingAllDocsTests.js | 0 .../docstore/test/acceptance/{coffee => js}/GettingDocsTests.js | 0 .../docstore/test/acceptance/{coffee => js}/UpdatingDocsTests.js | 0 .../test/acceptance/{coffee => js}/helpers/DocstoreApp.js | 0 .../test/acceptance/{coffee => js}/helpers/DocstoreClient.js | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename services/docstore/test/acceptance/{coffee => js}/ArchiveDocsTests.js (100%) rename services/docstore/test/acceptance/{coffee => js}/DeletingDocsTests.js (100%) rename services/docstore/test/acceptance/{coffee => js}/GettingAllDocsTests.js (100%) rename services/docstore/test/acceptance/{coffee => js}/GettingDocsTests.js (100%) rename services/docstore/test/acceptance/{coffee => js}/UpdatingDocsTests.js (100%) rename services/docstore/test/acceptance/{coffee => js}/helpers/DocstoreApp.js (100%) rename services/docstore/test/acceptance/{coffee => js}/helpers/DocstoreClient.js (100%) diff --git a/services/docstore/test/acceptance/coffee/ArchiveDocsTests.js b/services/docstore/test/acceptance/js/ArchiveDocsTests.js similarity index 100% rename from services/docstore/test/acceptance/coffee/ArchiveDocsTests.js rename to services/docstore/test/acceptance/js/ArchiveDocsTests.js diff --git a/services/docstore/test/acceptance/coffee/DeletingDocsTests.js b/services/docstore/test/acceptance/js/DeletingDocsTests.js similarity index 100% rename from services/docstore/test/acceptance/coffee/DeletingDocsTests.js rename to services/docstore/test/acceptance/js/DeletingDocsTests.js diff --git a/services/docstore/test/acceptance/coffee/GettingAllDocsTests.js b/services/docstore/test/acceptance/js/GettingAllDocsTests.js similarity index 100% rename from services/docstore/test/acceptance/coffee/GettingAllDocsTests.js rename to services/docstore/test/acceptance/js/GettingAllDocsTests.js diff --git a/services/docstore/test/acceptance/coffee/GettingDocsTests.js b/services/docstore/test/acceptance/js/GettingDocsTests.js similarity index 100% rename from services/docstore/test/acceptance/coffee/GettingDocsTests.js rename to services/docstore/test/acceptance/js/GettingDocsTests.js diff --git a/services/docstore/test/acceptance/coffee/UpdatingDocsTests.js b/services/docstore/test/acceptance/js/UpdatingDocsTests.js similarity index 100% rename from services/docstore/test/acceptance/coffee/UpdatingDocsTests.js rename to services/docstore/test/acceptance/js/UpdatingDocsTests.js diff --git a/services/docstore/test/acceptance/coffee/helpers/DocstoreApp.js b/services/docstore/test/acceptance/js/helpers/DocstoreApp.js similarity index 100% rename from services/docstore/test/acceptance/coffee/helpers/DocstoreApp.js rename to services/docstore/test/acceptance/js/helpers/DocstoreApp.js diff --git a/services/docstore/test/acceptance/coffee/helpers/DocstoreClient.js b/services/docstore/test/acceptance/js/helpers/DocstoreClient.js similarity index 100% rename from services/docstore/test/acceptance/coffee/helpers/DocstoreClient.js rename to services/docstore/test/acceptance/js/helpers/DocstoreClient.js From 785a6cb5444d9795c85a9882aaad9961c0e829ea Mon Sep 17 00:00:00 2001 From: Simon Detheridge <s@sd.ai> Date: Sun, 16 Feb 2020 14:03:09 +0000 Subject: [PATCH 18/27] prettier: convert test/acceptance decaffeinated files to Prettier format --- .../test/acceptance/js/ArchiveDocsTests.js | 1561 +++++++++++------ .../test/acceptance/js/DeletingDocsTests.js | 234 +-- .../test/acceptance/js/GettingAllDocsTests.js | 169 +- .../test/acceptance/js/GettingDocsTests.js | 187 +- .../test/acceptance/js/UpdatingDocsTests.js | 733 +++++--- .../test/acceptance/js/helpers/DocstoreApp.js | 62 +- .../acceptance/js/helpers/DocstoreClient.js | 183 +- 7 files changed, 2012 insertions(+), 1117 deletions(-) diff --git a/services/docstore/test/acceptance/js/ArchiveDocsTests.js b/services/docstore/test/acceptance/js/ArchiveDocsTests.js index 69a3ec2308..67d5d0e828 100644 --- a/services/docstore/test/acceptance/js/ArchiveDocsTests.js +++ b/services/docstore/test/acceptance/js/ArchiveDocsTests.js @@ -12,514 +12,1097 @@ * DS207: Consider shorter variations of null checks * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const sinon = require("sinon"); -const chai = require("chai"); -const should = chai.should(); -const {db, ObjectId, ISODate} = require("../../../app/js/mongojs"); -const async = require("async"); -const Settings = require("settings-sharelatex"); -const DocArchiveManager = require("../../../app/js/DocArchiveManager.js"); -const request = require("request"); -const DocstoreApp = require("./helpers/DocstoreApp"); -const DocstoreClient = require("./helpers/DocstoreClient"); +const sinon = require('sinon') +const chai = require('chai') +const should = chai.should() +const { db, ObjectId, ISODate } = require('../../../app/js/mongojs') +const async = require('async') +const Settings = require('settings-sharelatex') +const DocArchiveManager = require('../../../app/js/DocArchiveManager.js') +const request = require('request') +const DocstoreApp = require('./helpers/DocstoreApp') +const DocstoreClient = require('./helpers/DocstoreClient') +describe('Archiving', function() { + before(function(done) { + return DocstoreApp.ensureRunning(done) + }) -describe("Archiving", function() { + describe('multiple docs in a project', function() { + before(function(done) { + this.project_id = ObjectId() + this.docs = [ + { + _id: ObjectId(), + lines: ['one', 'two', 'three'], + ranges: {}, + version: 2 + }, + { + _id: ObjectId(), + lines: ['aaa', 'bbb', 'ccc'], + ranges: {}, + version: 4 + } + ] + const jobs = Array.from(this.docs).map(doc => + (doc => { + return callback => { + return DocstoreClient.createDoc( + this.project_id, + doc._id, + doc.lines, + doc.version, + doc.ranges, + callback + ) + } + })(doc) + ) - before(function(done) { return DocstoreApp.ensureRunning(done); }); + return async.series(jobs, error => { + if (error != null) { + throw error + } + return DocstoreClient.archiveAllDoc(this.project_id, (error, res) => { + this.res = res + return done() + }) + }) + }) - describe("multiple docs in a project", function() { - before(function(done) { - this.project_id = ObjectId(); - this.docs = [{ - _id: ObjectId(), - lines: ["one", "two", "three"], - ranges: {}, - version: 2 - }, { - _id: ObjectId(), - lines: ["aaa", "bbb", "ccc"], - ranges: {}, - version: 4 - }]; - const jobs = Array.from(this.docs).map((doc) => - (doc => { - return callback => { - return DocstoreClient.createDoc(this.project_id, doc._id, doc.lines, doc.version, doc.ranges, callback); - }; - })(doc)); + it('should archive all the docs', function(done) { + this.res.statusCode.should.equal(204) + return done() + }) - return async.series(jobs, error => { - if (error != null) { throw error; } - return DocstoreClient.archiveAllDoc(this.project_id, (error, res) => { - this.res = res; - return done(); - }); - }); - }); + it('should set inS3 and unset lines and ranges in each doc', function(done) { + const jobs = Array.from(this.docs).map(doc => + (doc => { + return callback => { + return db.docs.findOne({ _id: doc._id }, (error, doc) => { + should.not.exist(doc.lines) + should.not.exist(doc.ranges) + doc.inS3.should.equal(true) + return callback() + }) + } + })(doc) + ) + return async.series(jobs, done) + }) - it("should archive all the docs", function(done) { - this.res.statusCode.should.equal(204); - return done(); - }); + it('should set the docs in s3 correctly', function(done) { + const jobs = Array.from(this.docs).map(doc => + (doc => { + return callback => { + return DocstoreClient.getS3Doc( + this.project_id, + doc._id, + (error, res, s3_doc) => { + s3_doc.lines.should.deep.equal(doc.lines) + s3_doc.ranges.should.deep.equal(doc.ranges) + return callback() + } + ) + } + })(doc) + ) + return async.series(jobs, done) + }) - it("should set inS3 and unset lines and ranges in each doc", function(done) { - const jobs = Array.from(this.docs).map((doc) => - (doc => { - return callback => { - return db.docs.findOne({_id: doc._id}, (error, doc) => { - should.not.exist(doc.lines); - should.not.exist(doc.ranges); - doc.inS3.should.equal(true); - return callback(); - }); - }; - })(doc)); - return async.series(jobs, done); - }); + return describe('after unarchiving from a request for the project', function() { + before(function(done) { + return DocstoreClient.getAllDocs( + this.project_id, + (error, res, fetched_docs) => { + this.fetched_docs = fetched_docs + if (error != null) { + throw error + } + return done() + } + ) + }) - it("should set the docs in s3 correctly", function(done) { - const jobs = Array.from(this.docs).map((doc) => - (doc => { - return callback => { - return DocstoreClient.getS3Doc(this.project_id, doc._id, (error, res, s3_doc) => { - s3_doc.lines.should.deep.equal(doc.lines); - s3_doc.ranges.should.deep.equal(doc.ranges); - return callback(); - }); - }; - })(doc)); - return async.series(jobs, done); - }); - - return describe("after unarchiving from a request for the project", function() { - before(function(done) { - return DocstoreClient.getAllDocs(this.project_id, (error, res, fetched_docs) => { - this.fetched_docs = fetched_docs; - if (error != null) { throw error; } - return done(); - }); - }); - - it("should return the docs", function(done) { - for (let i = 0; i < this.fetched_docs.length; i++) { - const doc = this.fetched_docs[i]; - doc.lines.should.deep.equal(this.docs[i].lines); - } - return done(); - }); - - return it("should restore the docs to mongo", function(done) { - const jobs = Array.from(this.docs).map((doc, i) => - ((doc, i) => { - return callback => { - return db.docs.findOne({_id: doc._id}, (error, doc) => { - doc.lines.should.deep.equal(this.docs[i].lines); - doc.ranges.should.deep.equal(this.docs[i].ranges); - should.not.exist(doc.inS3); - return callback(); - }); - }; - })(doc, i)); - return async.series(jobs, done); - }); - }); - }); - - describe("a deleted doc", function() { - before(function(done) { - this.project_id = ObjectId(); - this.doc = { - _id: ObjectId(), - lines: ["one", "two", "three"], - ranges: {}, - version: 2 - }; - return DocstoreClient.createDoc(this.project_id, this.doc._id, this.doc.lines, this.doc.version, this.doc.ranges, error => { - if (error != null) { throw error; } - return DocstoreClient.deleteDoc(this.project_id, this.doc._id, error => { - if (error != null) { throw error; } - return DocstoreClient.archiveAllDoc(this.project_id, (error, res) => { - this.res = res; - if (error != null) { throw error; } - return done(); - }); - }); - }); - }); - - it("should successully archive the docs", function(done) { - this.res.statusCode.should.equal(204); - return done(); - }); + it('should return the docs', function(done) { + for (let i = 0; i < this.fetched_docs.length; i++) { + const doc = this.fetched_docs[i] + doc.lines.should.deep.equal(this.docs[i].lines) + } + return done() + }) - it("should set inS3 and unset lines and ranges in each doc", function(done) { - return db.docs.findOne({_id: this.doc._id}, (error, doc) => { - if (error != null) { throw error; } - should.not.exist(doc.lines); - should.not.exist(doc.ranges); - doc.inS3.should.equal(true); - doc.deleted.should.equal(true); - return done(); - }); - }); - - it("should set the doc in s3 correctly", function(done) { - return DocstoreClient.getS3Doc(this.project_id, this.doc._id, (error, res, s3_doc) => { - if (error != null) { throw error; } - s3_doc.lines.should.deep.equal(this.doc.lines); - s3_doc.ranges.should.deep.equal(this.doc.ranges); - return done(); - }); - }); - - return describe("after unarchiving from a request for the project", function() { - before(function(done) { - return DocstoreClient.getAllDocs(this.project_id, (error, res, fetched_docs) => { - this.fetched_docs = fetched_docs; - if (error != null) { throw error; } - return done(); - }); - }); - - it("should not included the deleted", function(done) { - this.fetched_docs.length.should.equal(0); - return done(); - }); - - return it("should restore the doc to mongo", function(done) { - return db.docs.findOne({_id: this.doc._id}, (error, doc) => { - if (error != null) { throw error; } - doc.lines.should.deep.equal(this.doc.lines); - doc.ranges.should.deep.equal(this.doc.ranges); - should.not.exist(doc.inS3); - doc.deleted.should.equal(true); - return done(); - }); - }); - }); - }); - - describe("a doc with large lines", function() { - before(function(done) { - this.project_id = ObjectId(); - this.timeout(1000 * 30); - const quarterMegInBytes = 250000; - const big_line = require("crypto").randomBytes(quarterMegInBytes).toString("hex"); - this.doc = { - _id: ObjectId(), - lines: [big_line, big_line, big_line, big_line], - ranges: {}, - version: 2 - }; - return DocstoreClient.createDoc(this.project_id, this.doc._id, this.doc.lines, this.doc.version, this.doc.ranges, error => { - if (error != null) { throw error; } - return DocstoreClient.archiveAllDoc(this.project_id, (error, res) => { - this.res = res; - if (error != null) { throw error; } - return done(); - }); - }); - }); - - it("should successully archive the docs", function(done) { - this.res.statusCode.should.equal(204); - return done(); - }); + return it('should restore the docs to mongo', function(done) { + const jobs = Array.from(this.docs).map((doc, i) => + ((doc, i) => { + return callback => { + return db.docs.findOne({ _id: doc._id }, (error, doc) => { + doc.lines.should.deep.equal(this.docs[i].lines) + doc.ranges.should.deep.equal(this.docs[i].ranges) + should.not.exist(doc.inS3) + return callback() + }) + } + })(doc, i) + ) + return async.series(jobs, done) + }) + }) + }) - it("should set inS3 and unset lines and ranges in each doc", function(done) { - return db.docs.findOne({_id: this.doc._id}, (error, doc) => { - if (error != null) { throw error; } - should.not.exist(doc.lines); - should.not.exist(doc.ranges); - doc.inS3.should.equal(true); - return done(); - }); - }); + describe('a deleted doc', function() { + before(function(done) { + this.project_id = ObjectId() + this.doc = { + _id: ObjectId(), + lines: ['one', 'two', 'three'], + ranges: {}, + version: 2 + } + return DocstoreClient.createDoc( + this.project_id, + this.doc._id, + this.doc.lines, + this.doc.version, + this.doc.ranges, + error => { + if (error != null) { + throw error + } + return DocstoreClient.deleteDoc( + this.project_id, + this.doc._id, + error => { + if (error != null) { + throw error + } + return DocstoreClient.archiveAllDoc( + this.project_id, + (error, res) => { + this.res = res + if (error != null) { + throw error + } + return done() + } + ) + } + ) + } + ) + }) - it("should set the doc in s3 correctly", function(done) { - return DocstoreClient.getS3Doc(this.project_id, this.doc._id, (error, res, s3_doc) => { - if (error != null) { throw error; } - s3_doc.lines.should.deep.equal(this.doc.lines); - s3_doc.ranges.should.deep.equal(this.doc.ranges); - return done(); - }); - }); - - return describe("after unarchiving from a request for the project", function() { - before(function(done) { - return DocstoreClient.getAllDocs(this.project_id, (error, res, fetched_docs) => { - this.fetched_docs = fetched_docs; - if (error != null) { throw error; } - return done(); - }); - }); - - return it("should restore the doc to mongo", function(done) { - return db.docs.findOne({_id: this.doc._id}, (error, doc) => { - if (error != null) { throw error; } - doc.lines.should.deep.equal(this.doc.lines); - doc.ranges.should.deep.equal(this.doc.ranges); - should.not.exist(doc.inS3); - return done(); - }); - }); - }); - }); - - describe("a doc with naughty strings", function() { - before(function(done) { - this.project_id = ObjectId(); - this.doc = { - _id: ObjectId(), - lines: [ "", "undefined", "undef", "null", "NULL", "(null)", "nil", "NIL", "true", "false", "True", "False", "None", "\\", "\\\\", "0", "1", "1.00", "$1.00", "1/2", "1E2", "1E02", "1E+02", "-1", "-1.00", "-$1.00", "-1/2", "-1E2", "-1E02", "-1E+02", "1/0", "0/0", "-2147483648/-1", "-9223372036854775808/-1", "0.00", "0..0", ".", "0.0.0", "0,00", "0,,0", ",", "0,0,0", "0.0/0", "1.0/0.0", "0.0/0.0", "1,0/0,0", "0,0/0,0", "--1", "-", "-.", "-,", "999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999", "NaN", "Infinity", "-Infinity", "0x0", "0xffffffff", "0xffffffffffffffff", "0xabad1dea", "123456789012345678901234567890123456789", "1,000.00", "1 000.00", "1'000.00", "1,000,000.00", "1 000 000.00", "1'000'000.00", "1.000,00", "1 000,00", "1'000,00", "1.000.000,00", "1 000i̳̞v̢͇ḙ͎͟-҉̭̩̼͔m̤̭̫i͕͇̝̦n̗͙ḍ̟ ̯̲͕͞ǫ̟̯̰̲͙̻̝f ̪̰̰̗̖̭̘͘c̦͍̲̞͍̩̙ḥ͚a̮͎̟̙͜ơ̩̹͎s̤.̝̝ ҉Z̡̖̜͖̰̣͉̜a͖̰͙̬͡l̲̫̳͍̩g̡̟̼̱͚̞̬ͅo̗͜.̟", "̦H̬̤̗̤͝e͜ ̜̥̝̻͍̟́w̕h̖̯͓o̝͙̖͎̱̮ ҉̺̙̞̟͈W̷̼̭a̺̪͍į͈͕̭͙̯̜t̶̼̮s̘͙͖̕ ̠̫̠B̻͍͙͉̳ͅe̵h̵̬͇̫͙i̹͓̳̳̮͎̫̕n͟d̴̪̜̖ ̰͉̩͇͙̲͞ͅT͖̼͓̪͢h͏͓̮̻e̬̝̟ͅ ̤̹̝W͙̞̝͔͇͝ͅa͏͓͔̹̼̣l̴͔̰̤̟͔ḽ̫.͕", "Z̮̞̠͙͔ͅḀ̗̞͈̻̗Ḷ͙͎̯̹̞͓G̻O̭̗̮", "˙ɐnbᴉlɐ ɐuƃɐɯ ǝɹolop ʇǝ ǝɹoqɐl ʇn ʇunpᴉpᴉɔuᴉ ɹodɯǝʇ poɯsnᴉǝ op pǝs 'ʇᴉlǝ ƃuᴉɔsᴉdᴉpɐ ɹnʇǝʇɔǝsuoɔ 'ʇǝɯɐ ʇᴉs ɹolop ɯnsdᴉ ɯǝɹo˥", "00˙Ɩ$-", "The quick brown fox jumps over the lazy dog", "𝐓𝐡𝐞 𝐪𝐮𝐢𝐜𝐤 𝐛𝐫𝐨𝐰𝐧 𝐟𝐨𝐱 𝐣𝐮𝐦𝐩𝐬 𝐨𝐯𝐞𝐫 𝐭𝐡𝐞 𝐥𝐚𝐳𝐲 𝐝𝐨𝐠", "𝕿𝖍𝖊 𝖖𝖚𝖎𝖈𝖐 𝖇𝖗𝖔𝖜𝖓 𝖋𝖔𝖝 𝖏𝖚𝖒𝖕𝖘 𝖔𝖛𝖊𝖗 𝖙𝖍𝖊 𝖑𝖆𝖟𝖞 𝖉𝖔𝖌", "𝑻𝒉𝒆 𝒒𝒖𝒊𝒄𝒌 𝒃𝒓𝒐𝒘𝒏 𝒇𝒐𝒙 𝒋𝒖𝒎𝒑𝒔 𝒐𝒗𝒆𝒓 𝒕𝒉𝒆 𝒍𝒂𝒛𝒚 𝒅𝒐𝒈", "𝓣𝓱𝓮 𝓺𝓾𝓲𝓬𝓴 𝓫𝓻𝓸𝔀𝓷 𝓯𝓸𝔁 𝓳𝓾𝓶𝓹𝓼 𝓸𝓿𝓮𝓻 𝓽𝓱𝓮 𝓵𝓪𝔃𝔂 𝓭𝓸𝓰", "𝕋𝕙𝕖 𝕢𝕦𝕚𝕔𝕜 𝕓𝕣𝕠𝕨𝕟 𝕗𝕠𝕩 𝕛𝕦𝕞𝕡𝕤 𝕠𝕧𝕖𝕣 𝕥𝕙𝕖 𝕝𝕒𝕫𝕪 𝕕𝕠𝕘", "𝚃𝚑𝚎 𝚚𝚞𝚒𝚌𝚔 𝚋𝚛𝚘𝚠𝚗 𝚏𝚘𝚡 𝚓𝚞𝚖𝚙𝚜 𝚘𝚟𝚎𝚛 𝚝𝚑𝚎 𝚕𝚊𝚣𝚢 𝚍𝚘𝚐", "⒯⒣⒠ ⒬⒰⒤⒞⒦ ⒝⒭⒪⒲⒩ ⒡⒪⒳ ⒥⒰⒨⒫⒮ ⒪⒱⒠⒭ ⒯⒣⒠ ⒧⒜⒵⒴ ⒟⒪⒢", "<script>alert(123)</script>", "<script>alert('123');</script>", "<img src=x onerror=alert(123) />", "<svg><script>123<1>alert(123)</script> ", "\"><script>alert(123)</script>", "'><script>alert(123)</script>", "><script>alert(123)</script>", "</script><script>alert(123)</script>", "< / script >< script >alert(123)< / script >", " onfocus=JaVaSCript:alert(123) autofocus ", "\" onfocus=JaVaSCript:alert(123) autofocus ", "' onfocus=JaVaSCript:alert(123) autofocus ", "<script>alert(123)</script>", "<sc<script>ript>alert(123)</sc</script>ript>", "--><script>alert(123)</script>", "\";alert(123);t=\"", "';alert(123);t='", "JavaSCript:alert(123)", ";alert(123);", "src=JaVaSCript:prompt(132)", "\"><script>alert(123);</script x=\"", "'><script>alert(123);</script x='", "><script>alert(123);</script x=", "\" autofocus onkeyup=\"javascript:alert(123)", "' autofocus onkeyup='javascript:alert(123)", "<script\\x20type=\"text/javascript\">javascript:alert(1);</script>", "<script\\x3Etype=\"text/javascript\">javascript:alert(1);</script>", "<script\\x0Dtype=\"text/javascript\">javascript:alert(1);</script>", "<script\\x09type=\"text/javascript\">javascript:alert(1);</script>", "<script\\x0Ctype=\"text/javascript\">javascript:alert(1);</script>", "<script\\x2Ftype=\"text/javascript\">javascript:alert(1);</script>", "<script\\x0Atype=\"text/javascript\">javascript:alert(1);</script>", "'`\"><\\x3Cscript>javascript:alert(1)</script> ", "'`\"><\\x00script>javascript:alert(1)</script>", "ABC<div style=\"x\\x3Aexpression(javascript:alert(1)\">DEF", "ABC<div style=\"x:expression\\x5C(javascript:alert(1)\">DEF", "ABC<div style=\"x:expression\\x00(javascript:alert(1)\">DEF", "ABC<div style=\"x:exp\\x00ression(javascript:alert(1)\">DEF", "ABC<div style=\"x:exp\\x5Cression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\x0Aexpression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\x09expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xE3\\x80\\x80expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xE2\\x80\\x84expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xC2\\xA0expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xE2\\x80\\x80expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xE2\\x80\\x8Aexpression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\x0Dexpression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\x0Cexpression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xE2\\x80\\x87expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xEF\\xBB\\xBFexpression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\x20expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xE2\\x80\\x88expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\x00expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xE2\\x80\\x8Bexpression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xE2\\x80\\x86expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xE2\\x80\\x85expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xE2\\x80\\x82expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\x0Bexpression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xE2\\x80\\x81expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xE2\\x80\\x83expression(javascript:alert(1)\">DEF", "ABC<div style=\"x:\\xE2\\x80\\x89expression(javascript:alert(1)\">DEF", "<a href=\"\\x0Bjavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x0Fjavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xC2\\xA0javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x05javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE1\\xA0\\x8Ejavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x18javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x11javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\x88javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\x89javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\x80javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x17javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x03javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x0Ejavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x1Ajavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x00javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x10javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\x82javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x20javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x13javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x09javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\x8Ajavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x14javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x19javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\xAFjavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x1Fjavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\x81javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x1Djavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\x87javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x07javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE1\\x9A\\x80javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\x83javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x04javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x01javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x08javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\x84javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\x86javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE3\\x80\\x80javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x12javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x0Djavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x0Ajavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x0Cjavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x15javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\xA8javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x16javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x02javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x1Bjavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x06javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\xA9javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x80\\x85javascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x1Ejavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\xE2\\x81\\x9Fjavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"\\x1Cjavascript:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"javascript\\x00:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"javascript\\x3A:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"javascript\\x09:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"javascript\\x0D:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "<a href=\"javascript\\x0A:javascript:alert(1)\" id=\"fuzzelement1\">test</a>", "`\"'><img src=xxx:x \\x0Aonerror=javascript:alert(1)>", "`\"'><img src=xxx:x \\x22onerror=javascript:alert(1)>", "`\"'><img src=xxx:x \\x0Bonerror=javascript:alert(1)>", "`\"'><img src=xxx:x \\x0Donerror=javascript:alert(1)>", "`\"'><img src=xxx:x \\x2Fonerror=javascript:alert(1)>", "`\"'><img src=xxx:x \\x09onerror=javascript:alert(1)>", "`\"'><img src=xxx:x \\x0Conerror=javascript:alert(1)>", "`\"'><img src=xxx:x \\x00onerror=javascript:alert(1)>", "`\"'><img src=xxx:x \\x27onerror=javascript:alert(1)>", "`\"'><img src=xxx:x \\x20onerror=javascript:alert(1)>", "\"`'><script>\\x3Bjavascript:alert(1)</script>", "\"`'><script>\\x0Djavascript:alert(1)</script>", "\"`'><script>\\xEF\\xBB\\xBFjavascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\x81javascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\x84javascript:alert(1)</script>", "\"`'><script>\\xE3\\x80\\x80javascript:alert(1)</script>", "\"`'><script>\\x09javascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\x89javascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\x85javascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\x88javascript:alert(1)</script>", "\"`'><script>\\x00javascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\xA8javascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\x8Ajavascript:alert(1)</script>", "\"`'><script>\\xE1\\x9A\\x80javascript:alert(1)</script>", "\"`'><script>\\x0Cjavascript:alert(1)</script>", "\"`'><script>\\x2Bjavascript:alert(1)</script>", "\"`'><script>\\xF0\\x90\\x96\\x9Ajavascript:alert(1)</script>", "\"`'><script>-javascript:alert(1)</script>", "\"`'><script>\\x0Ajavascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\xAFjavascript:alert(1)</script>", "\"`'><script>\\x7Ejavascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\x87javascript:alert(1)</script>", "\"`'><script>\\xE2\\x81\\x9Fjavascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\xA9javascript:alert(1)</script>", "\"`'><script>\\xC2\\x85javascript:alert(1)</script>", "\"`'><script>\\xEF\\xBF\\xAEjavascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\x83javascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\x8Bjavascript:alert(1)</script>", "\"`'><script>\\xEF\\xBF\\xBEjavascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\x80javascript:alert(1)</script>", "\"`'><script>\\x21javascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\x82javascript:alert(1)</script>", "\"`'><script>\\xE2\\x80\\x86javascript:alert(1)</script>", "\"`'><script>\\xE1\\xA0\\x8Ejavascript:alert(1)</script>", "\"`'><script>\\x0Bjavascript:alert(1)</script>", "\"`'><script>\\x20javascript:alert(1)</script>", "\"`'><script>\\xC2\\xA0javascript:alert(1)</script>", "<img \\x00src=x onerror=\"alert(1)\">", "<img \\x47src=x onerror=\"javascript:alert(1)\">", "<img \\x11src=x onerror=\"javascript:alert(1)\">", "<img \\x12src=x onerror=\"javascript:alert(1)\">", "<img\\x47src=x onerror=\"javascript:alert(1)\">", "<img\\x10src=x onerror=\"javascript:alert(1)\">", "<img\\x13src=x onerror=\"javascript:alert(1)\">", "<img\\x32src=x onerror=\"javascript:alert(1)\">", "<img\\x47src=x onerror=\"javascript:alert(1)\">", "<img\\x11src=x onerror=\"javascript:alert(1)\">", "<img \\x47src=x onerror=\"javascript:alert(1)\">", "<img \\x34src=x onerror=\"javascript:alert(1)\">", "<img \\x39src=x onerror=\"javascript:alert(1)\">", "<img \\x00src=x onerror=\"javascript:alert(1)\">", "<img src\\x09=x onerror=\"javascript:alert(1)\">", "<img src\\x10=x onerror=\"javascript:alert(1)\">", "<img src\\x13=x onerror=\"javascript:alert(1)\">", "<img src\\x32=x onerror=\"javascript:alert(1)\">", "<img src\\x12=x onerror=\"javascript:alert(1)\">", "<img src\\x11=x onerror=\"javascript:alert(1)\">", "<img src\\x00=x onerror=\"javascript:alert(1)\">", "<img src\\x47=x onerror=\"javascript:alert(1)\">", "<img src=x\\x09onerror=\"javascript:alert(1)\">", "<img src=x\\x10onerror=\"javascript:alert(1)\">", "<img src=x\\x11onerror=\"javascript:alert(1)\">", "<img src=x\\x12onerror=\"javascript:alert(1)\">", "<img src=x\\x13onerror=\"javascript:alert(1)\">", "<img[a][b][c]src[d]=x[e]onerror=[f]\"alert(1)\">", "<img src=x onerror=\\x09\"javascript:alert(1)\">", "<img src=x onerror=\\x10\"javascript:alert(1)\">", "<img src=x onerror=\\x11\"javascript:alert(1)\">", "<img src=x onerror=\\x12\"javascript:alert(1)\">", "<img src=x onerror=\\x32\"javascript:alert(1)\">", "<img src=x onerror=\\x00\"javascript:alert(1)\">", "<a href=java script:javascript:alert(1)>XXX</a>", "<img src=\"x` `<script>javascript:alert(1)</script>\"` `>", "<img src onerror /\" '\"= alt=javascript:alert(1)//\">", "<title onpropertychange=javascript:alert(1)>", "<a href=http://foo.bar/#x=`y></a><img alt=\"`><img src=x:x onerror=javascript:alert(1)></a>\">", "<!--[if]><script>javascript:alert(1)</script -->", "<!--[if<img src=x onerror=javascript:alert(1)//]> -->", "<script src=\"/\\%(jscript)s\"></script>", "<script src=\"\\\\%(jscript)s\"></script>", "<IMG \"\"\"><SCRIPT>alert(\"XSS\")</SCRIPT>\">", "<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>", "<IMG SRC=# onmouseover=\"alert('xxs')\">", "<IMG SRC= onmouseover=\"alert('xxs')\">", "<IMG onmouseover=\"alert('xxs')\">", "<IMG SRC=javascript:alert('XSS')>", "<IMG SRC=javascript:alert('XSS')>", "<IMG SRC=javascript:alert('XSS')>", "<IMG SRC=\"jav ascript:alert('XSS');\">", "<IMG SRC=\"jav ascript:alert('XSS');\">", "<IMG SRC=\"jav ascript:alert('XSS');\">", "<IMG SRC=\"jav ascript:alert('XSS');\">", "perl -e 'print \"<IMG SRC=java\\0script:alert(\\\"XSS\\\")>\";' > out", "<IMG SRC=\"  javascript:alert('XSS');\">", "<SCRIPT/XSS SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT>", "<BODY onload!#$%&()*~+-_.,:;?@[/|\\]^`=alert(\"XSS\")>", "<SCRIPT/SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT>", "<<SCRIPT>alert(\"XSS\");//<</SCRIPT>", "<SCRIPT SRC=http://ha.ckers.org/xss.js?< B >", "<SCRIPT SRC=//ha.ckers.org/.j>", "<IMG SRC=\"javascript:alert('XSS')\"", "<iframe src=http://ha.ckers.org/scriptlet.html <", "\\\";alert('XSS');//", "<plaintext>", "1;DROP TABLE users", "1'; DROP TABLE users-- 1", "' OR 1=1 -- 1", "' OR '1'='1", "-", "--", "--version", "--help", "$USER", "/dev/null; touch /tmp/blns.fail ; echo", "`touch /tmp/blns.fail`", "$(touch /tmp/blns.fail)", "@{[system \"touch /tmp/blns.fail\"]}", "eval(\"puts 'hello world'\")", "System(\"ls -al /\")", "`ls -al /`", "Kernel.exec(\"ls -al /\")", "Kernel.exit(1)", "%x('ls -al /')", "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><!DOCTYPE foo [ <!ELEMENT foo ANY ><!ENTITY xxe SYSTEM \"file:///etc/passwd\" >]><foo>&xxe;</foo>", "$HOME", "$ENV{'HOME'}", "%d", "%s", "%*.*s", "../../../../../../../../../../../etc/passwd%00", "../../../../../../../../../../../etc/hosts", "() { 0; }; touch /tmp/blns.shellshock1.fail;", "() { _; } >_[$($())] { touch /tmp/blns.shellshock2.fail; }", "CON", "PRN", "AUX", "CLOCK$", "NUL", "A:", "ZZ:", "COM1", "LPT1", "LPT2", "LPT3", "COM2", "COM3", "COM4", "Scunthorpe General Hospital", "Penistone Community Church", "Lightwater Country Park", "Jimmy Clitheroe", "Horniman Museum", "shitake mushrooms", "RomansInSussex.co.uk", "http://www.cum.qc.ca/", "Craig Cockburn, Software Specialist", "Linda Callahan", "Dr. Herman I. Libshitz", "magna cum laude", "Super Bowl XXX", "medieval erection of parapets", "evaluate", "mocha", "expression", "Arsenal canal", "classic", "Tyson Gay", "If you're reading this, you've been in a coma for almost 20 years now. We're trying a new technique. We don't know where this message will end up in your dream, but we hope it works. Please wake up, we miss you.", "Roses are \u001b[0;31mred\u001b[0m, violets are \u001b[0;34mblue. Hope you enjoy terminal hue", "But now...\u001b[20Cfor my greatest trick...\u001b[8m", "The quic\b\b\b\b\b\bk brown fo\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007x... [Beeeep]", "Powerلُلُصّبُلُلصّبُررً ॣ ॣh ॣ ॣ冗" ], - ranges: {}, - version: 2 - }; - return DocstoreClient.createDoc(this.project_id, this.doc._id, this.doc.lines, this.doc.version, this.doc.ranges, error => { - if (error != null) { throw error; } - return DocstoreClient.archiveAllDoc(this.project_id, (error, res) => { - this.res = res; - if (error != null) { throw error; } - return done(); - }); - }); - }); - - it("should successully archive the docs", function(done) { - this.res.statusCode.should.equal(204); - return done(); - }); + it('should successully archive the docs', function(done) { + this.res.statusCode.should.equal(204) + return done() + }) - it("should set inS3 and unset lines and ranges in each doc", function(done) { - return db.docs.findOne({_id: this.doc._id}, (error, doc) => { - if (error != null) { throw error; } - should.not.exist(doc.lines); - should.not.exist(doc.ranges); - doc.inS3.should.equal(true); - return done(); - }); - }); + it('should set inS3 and unset lines and ranges in each doc', function(done) { + return db.docs.findOne({ _id: this.doc._id }, (error, doc) => { + if (error != null) { + throw error + } + should.not.exist(doc.lines) + should.not.exist(doc.ranges) + doc.inS3.should.equal(true) + doc.deleted.should.equal(true) + return done() + }) + }) - it("should set the doc in s3 correctly", function(done) { - return DocstoreClient.getS3Doc(this.project_id, this.doc._id, (error, res, s3_doc) => { - if (error != null) { throw error; } - s3_doc.lines.should.deep.equal(this.doc.lines); - s3_doc.ranges.should.deep.equal(this.doc.ranges); - return done(); - }); - }); - - return describe("after unarchiving from a request for the project", function() { - before(function(done) { - return DocstoreClient.getAllDocs(this.project_id, (error, res, fetched_docs) => { - this.fetched_docs = fetched_docs; - if (error != null) { throw error; } - return done(); - }); - }); - - return it("should restore the doc to mongo", function(done) { - return db.docs.findOne({_id: this.doc._id}, (error, doc) => { - if (error != null) { throw error; } - doc.lines.should.deep.equal(this.doc.lines); - doc.ranges.should.deep.equal(this.doc.ranges); - should.not.exist(doc.inS3); - return done(); - }); - }); - }); - }); + it('should set the doc in s3 correctly', function(done) { + return DocstoreClient.getS3Doc( + this.project_id, + this.doc._id, + (error, res, s3_doc) => { + if (error != null) { + throw error + } + s3_doc.lines.should.deep.equal(this.doc.lines) + s3_doc.ranges.should.deep.equal(this.doc.ranges) + return done() + } + ) + }) - describe("a doc with ranges", function() { - before(function(done) { - this.project_id = ObjectId(); - this.doc = { - _id: ObjectId(), - lines: ["one", "two", "three"], - ranges: { - changes: - [{ - id : ObjectId(), - op : { "i" : "foo", "p" : 24 }, - metadata : { "user_id" : ObjectId(), "ts" : new Date("2017-01-27T16:10:44.194Z") } - }, { - id : ObjectId(), - op : { "d" : "bar", "p" : 50 }, - metadata : { "user_id" : ObjectId(), "ts" : new Date("2017-01-27T18:10:44.194Z") } - }], - comments: [{ - id: ObjectId(), - op: { "c" : "comment", "p" : 284, "t" : ObjectId() }, - metadata: { "user_id" : ObjectId(), "ts" : new Date("2017-01-26T14:22:04.869Z") } - }] - }, - version: 2 - }; - return DocstoreClient.createDoc(this.project_id, this.doc._id, this.doc.lines, this.doc.version, this.doc.ranges, error => { - if (error != null) { throw error; } - return DocstoreClient.archiveAllDoc(this.project_id, (error, res) => { - this.res = res; - if (error != null) { throw error; } - return done(); - }); - }); - }); - - it("should successully archive the docs", function(done) { - this.res.statusCode.should.equal(204); - return done(); - }); + return describe('after unarchiving from a request for the project', function() { + before(function(done) { + return DocstoreClient.getAllDocs( + this.project_id, + (error, res, fetched_docs) => { + this.fetched_docs = fetched_docs + if (error != null) { + throw error + } + return done() + } + ) + }) - it("should set inS3 and unset lines and ranges in each doc", function(done) { - return db.docs.findOne({_id: this.doc._id}, (error, doc) => { - if (error != null) { throw error; } - should.not.exist(doc.lines); - should.not.exist(doc.ranges); - doc.inS3.should.equal(true); - return done(); - }); - }); + it('should not included the deleted', function(done) { + this.fetched_docs.length.should.equal(0) + return done() + }) - it("should set the doc in s3 correctly", function(done) { - return DocstoreClient.getS3Doc(this.project_id, this.doc._id, (error, res, s3_doc) => { - if (error != null) { throw error; } - s3_doc.lines.should.deep.equal(this.doc.lines); - const ranges = JSON.parse(JSON.stringify(this.doc.ranges)); // ObjectId -> String - s3_doc.ranges.should.deep.equal(ranges); - return done(); - }); - }); - - return describe("after unarchiving from a request for the project", function() { - before(function(done) { - return DocstoreClient.getAllDocs(this.project_id, (error, res, fetched_docs) => { - this.fetched_docs = fetched_docs; - if (error != null) { throw error; } - return done(); - }); - }); - - return it("should restore the doc to mongo", function(done) { - return db.docs.findOne({_id: this.doc._id}, (error, doc) => { - if (error != null) { throw error; } - doc.lines.should.deep.equal(this.doc.lines); - doc.ranges.should.deep.equal(this.doc.ranges); - should.not.exist(doc.inS3); - return done(); - }); - }); - }); - }); + return it('should restore the doc to mongo', function(done) { + return db.docs.findOne({ _id: this.doc._id }, (error, doc) => { + if (error != null) { + throw error + } + doc.lines.should.deep.equal(this.doc.lines) + doc.ranges.should.deep.equal(this.doc.ranges) + should.not.exist(doc.inS3) + doc.deleted.should.equal(true) + return done() + }) + }) + }) + }) - describe("a doc that is archived twice", function() { - before(function(done) { - this.project_id = ObjectId(); - this.doc = { - _id: ObjectId(), - lines: ["abc", "def", "ghi"], - ranges: {}, - version: 2 - }; - return DocstoreClient.createDoc(this.project_id, this.doc._id, this.doc.lines, this.doc.version, this.doc.ranges, error => { - if (error != null) { throw error; } - return DocstoreClient.archiveAllDoc(this.project_id, (error, res) => { - this.res = res; - if (error != null) { throw error; } - this.res.statusCode.should.equal(204); - return DocstoreClient.archiveAllDoc(this.project_id, (error, res1) => { - this.res = res1; - if (error != null) { throw error; } - this.res.statusCode.should.equal(204); - return done(); - }); - }); - }); - }); + describe('a doc with large lines', function() { + before(function(done) { + this.project_id = ObjectId() + this.timeout(1000 * 30) + const quarterMegInBytes = 250000 + const big_line = require('crypto') + .randomBytes(quarterMegInBytes) + .toString('hex') + this.doc = { + _id: ObjectId(), + lines: [big_line, big_line, big_line, big_line], + ranges: {}, + version: 2 + } + return DocstoreClient.createDoc( + this.project_id, + this.doc._id, + this.doc.lines, + this.doc.version, + this.doc.ranges, + error => { + if (error != null) { + throw error + } + return DocstoreClient.archiveAllDoc(this.project_id, (error, res) => { + this.res = res + if (error != null) { + throw error + } + return done() + }) + } + ) + }) - it("should set inS3 and unset lines and ranges in each doc", function(done) { - return db.docs.findOne({_id: this.doc._id}, (error, doc) => { - if (error != null) { throw error; } - should.not.exist(doc.lines); - should.not.exist(doc.ranges); - doc.inS3.should.equal(true); - return done(); - }); - }); + it('should successully archive the docs', function(done) { + this.res.statusCode.should.equal(204) + return done() + }) - it("should set the doc in s3 correctly", function(done) { - return DocstoreClient.getS3Doc(this.project_id, this.doc._id, (error, res, s3_doc) => { - if (error != null) { throw error; } - s3_doc.lines.should.deep.equal(this.doc.lines); - s3_doc.ranges.should.deep.equal(this.doc.ranges); - return done(); - }); - }); - - return describe("after unarchiving from a request for the project", function() { - before(function(done) { - return DocstoreClient.getAllDocs(this.project_id, (error, res, fetched_docs) => { - this.fetched_docs = fetched_docs; - if (error != null) { throw error; } - return done(); - }); - }); - - return it("should restore the doc to mongo", function(done) { - return db.docs.findOne({_id: this.doc._id}, (error, doc) => { - if (error != null) { throw error; } - doc.lines.should.deep.equal(this.doc.lines); - doc.ranges.should.deep.equal(this.doc.ranges); - should.not.exist(doc.inS3); - return done(); - }); - }); - }); - }); + it('should set inS3 and unset lines and ranges in each doc', function(done) { + return db.docs.findOne({ _id: this.doc._id }, (error, doc) => { + if (error != null) { + throw error + } + should.not.exist(doc.lines) + should.not.exist(doc.ranges) + doc.inS3.should.equal(true) + return done() + }) + }) - return describe("a doc with the old schema (just an array of lines)", function() { - before(function(done) { - this.project_id = ObjectId(); - this.doc = { - _id: ObjectId(), - lines: ["abc", "def", "ghi"], - ranges: {}, - version: 2 - }; - const options = DocArchiveManager.buildS3Options(`${this.project_id}/${this.doc._id}`); - options.json = this.doc.lines; - return request.put(options, (error, res, body) => { - if (error != null) { throw error; } - res.statusCode.should.equal(200); - return db.docs.insert({ - project_id: this.project_id, - _id: this.doc._id, - rev: this.doc.version, - inS3: true - }, error => { - if (error != null) { throw error; } - return DocstoreClient.getAllDocs(this.project_id, (error, res, fetched_docs) => { - this.fetched_docs = fetched_docs; - if (error != null) { throw error; } - return done(); - }); - }); - }); - }); + it('should set the doc in s3 correctly', function(done) { + return DocstoreClient.getS3Doc( + this.project_id, + this.doc._id, + (error, res, s3_doc) => { + if (error != null) { + throw error + } + s3_doc.lines.should.deep.equal(this.doc.lines) + s3_doc.ranges.should.deep.equal(this.doc.ranges) + return done() + } + ) + }) - it("should restore the doc to mongo", function(done) { - return db.docs.findOne({_id: this.doc._id}, (error, doc) => { - if (error != null) { throw error; } - doc.lines.should.deep.equal(this.doc.lines); - should.not.exist(doc.inS3); - return done(); - }); - }); - - return it("should return the doc", function(done) { - this.fetched_docs[0].lines.should.deep.equal(this.doc.lines); - return done(); - }); - }); -}); + return describe('after unarchiving from a request for the project', function() { + before(function(done) { + return DocstoreClient.getAllDocs( + this.project_id, + (error, res, fetched_docs) => { + this.fetched_docs = fetched_docs + if (error != null) { + throw error + } + return done() + } + ) + }) + return it('should restore the doc to mongo', function(done) { + return db.docs.findOne({ _id: this.doc._id }, (error, doc) => { + if (error != null) { + throw error + } + doc.lines.should.deep.equal(this.doc.lines) + doc.ranges.should.deep.equal(this.doc.ranges) + should.not.exist(doc.inS3) + return done() + }) + }) + }) + }) + + describe('a doc with naughty strings', function() { + before(function(done) { + this.project_id = ObjectId() + this.doc = { + _id: ObjectId(), + lines: [ + '', + 'undefined', + 'undef', + 'null', + 'NULL', + '(null)', + 'nil', + 'NIL', + 'true', + 'false', + 'True', + 'False', + 'None', + '\\', + '\\\\', + '0', + '1', + '1.00', + '$1.00', + '1/2', + '1E2', + '1E02', + '1E+02', + '-1', + '-1.00', + '-$1.00', + '-1/2', + '-1E2', + '-1E02', + '-1E+02', + '1/0', + '0/0', + '-2147483648/-1', + '-9223372036854775808/-1', + '0.00', + '0..0', + '.', + '0.0.0', + '0,00', + '0,,0', + ',', + '0,0,0', + '0.0/0', + '1.0/0.0', + '0.0/0.0', + '1,0/0,0', + '0,0/0,0', + '--1', + '-', + '-.', + '-,', + '999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999', + 'NaN', + 'Infinity', + '-Infinity', + '0x0', + '0xffffffff', + '0xffffffffffffffff', + '0xabad1dea', + '123456789012345678901234567890123456789', + '1,000.00', + '1 000.00', + "1'000.00", + '1,000,000.00', + '1 000 000.00', + "1'000'000.00", + '1.000,00', + '1 000,00', + "1'000,00", + '1.000.000,00', + '1 000i̳̞v̢͇ḙ͎͟-҉̭̩̼͔m̤̭̫i͕͇̝̦n̗͙ḍ̟ ̯̲͕͞ǫ̟̯̰̲͙̻̝f ̪̰̰̗̖̭̘͘c̦͍̲̞͍̩̙ḥ͚a̮͎̟̙͜ơ̩̹͎s̤.̝̝ ҉Z̡̖̜͖̰̣͉̜a͖̰͙̬͡l̲̫̳͍̩g̡̟̼̱͚̞̬ͅo̗͜.̟', + '̦H̬̤̗̤͝e͜ ̜̥̝̻͍̟́w̕h̖̯͓o̝͙̖͎̱̮ ҉̺̙̞̟͈W̷̼̭a̺̪͍į͈͕̭͙̯̜t̶̼̮s̘͙͖̕ ̠̫̠B̻͍͙͉̳ͅe̵h̵̬͇̫͙i̹͓̳̳̮͎̫̕n͟d̴̪̜̖ ̰͉̩͇͙̲͞ͅT͖̼͓̪͢h͏͓̮̻e̬̝̟ͅ ̤̹̝W͙̞̝͔͇͝ͅa͏͓͔̹̼̣l̴͔̰̤̟͔ḽ̫.͕', + 'Z̮̞̠͙͔ͅḀ̗̞͈̻̗Ḷ͙͎̯̹̞͓G̻O̭̗̮', + "˙ɐnbᴉlɐ ɐuƃɐɯ ǝɹolop ʇǝ ǝɹoqɐl ʇn ʇunpᴉpᴉɔuᴉ ɹodɯǝʇ poɯsnᴉǝ op pǝs 'ʇᴉlǝ ƃuᴉɔsᴉdᴉpɐ ɹnʇǝʇɔǝsuoɔ 'ʇǝɯɐ ʇᴉs ɹolop ɯnsdᴉ ɯǝɹo˥", + '00˙Ɩ$-', + 'The quick brown fox jumps over the lazy dog', + '𝐓𝐡𝐞 𝐪𝐮𝐢𝐜𝐤 𝐛𝐫𝐨𝐰𝐧 𝐟𝐨𝐱 𝐣𝐮𝐦𝐩𝐬 𝐨𝐯𝐞𝐫 𝐭𝐡𝐞 𝐥𝐚𝐳𝐲 𝐝𝐨𝐠', + '𝕿𝖍𝖊 𝖖𝖚𝖎𝖈𝖐 𝖇𝖗𝖔𝖜𝖓 𝖋𝖔𝖝 𝖏𝖚𝖒𝖕𝖘 𝖔𝖛𝖊𝖗 𝖙𝖍𝖊 𝖑𝖆𝖟𝖞 𝖉𝖔𝖌', + '𝑻𝒉𝒆 𝒒𝒖𝒊𝒄𝒌 𝒃𝒓𝒐𝒘𝒏 𝒇𝒐𝒙 𝒋𝒖𝒎𝒑𝒔 𝒐𝒗𝒆𝒓 𝒕𝒉𝒆 𝒍𝒂𝒛𝒚 𝒅𝒐𝒈', + '𝓣𝓱𝓮 𝓺𝓾𝓲𝓬𝓴 𝓫𝓻𝓸𝔀𝓷 𝓯𝓸𝔁 𝓳𝓾𝓶𝓹𝓼 𝓸𝓿𝓮𝓻 𝓽𝓱𝓮 𝓵𝓪𝔃𝔂 𝓭𝓸𝓰', + '𝕋𝕙𝕖 𝕢𝕦𝕚𝕔𝕜 𝕓𝕣𝕠𝕨𝕟 𝕗𝕠𝕩 𝕛𝕦𝕞𝕡𝕤 𝕠𝕧𝕖𝕣 𝕥𝕙𝕖 𝕝𝕒𝕫𝕪 𝕕𝕠𝕘', + '𝚃𝚑𝚎 𝚚𝚞𝚒𝚌𝚔 𝚋𝚛𝚘𝚠𝚗 𝚏𝚘𝚡 𝚓𝚞𝚖𝚙𝚜 𝚘𝚟𝚎𝚛 𝚝𝚑𝚎 𝚕𝚊𝚣𝚢 𝚍𝚘𝚐', + '⒯⒣⒠ ⒬⒰⒤⒞⒦ ⒝⒭⒪⒲⒩ ⒡⒪⒳ ⒥⒰⒨⒫⒮ ⒪⒱⒠⒭ ⒯⒣⒠ ⒧⒜⒵⒴ ⒟⒪⒢', + '<script>alert(123)</script>', + '<script>alert('123');</script>', + '<img src=x onerror=alert(123) />', + '<svg><script>123<1>alert(123)</script> ', + '"><script>alert(123)</script>', + "'><script>alert(123)</script>", + '><script>alert(123)</script>', + '</script><script>alert(123)</script>', + '< / script >< script >alert(123)< / script >', + ' onfocus=JaVaSCript:alert(123) autofocus ', + '" onfocus=JaVaSCript:alert(123) autofocus ', + "' onfocus=JaVaSCript:alert(123) autofocus ", + '<script>alert(123)</script>', + '<sc<script>ript>alert(123)</sc</script>ript>', + '--><script>alert(123)</script>', + '";alert(123);t="', + "';alert(123);t='", + 'JavaSCript:alert(123)', + ';alert(123);', + 'src=JaVaSCript:prompt(132)', + '"><script>alert(123);</script x="', + "'><script>alert(123);</script x='", + '><script>alert(123);</script x=', + '" autofocus onkeyup="javascript:alert(123)', + "' autofocus onkeyup='javascript:alert(123)", + '<script\\x20type="text/javascript">javascript:alert(1);</script>', + '<script\\x3Etype="text/javascript">javascript:alert(1);</script>', + '<script\\x0Dtype="text/javascript">javascript:alert(1);</script>', + '<script\\x09type="text/javascript">javascript:alert(1);</script>', + '<script\\x0Ctype="text/javascript">javascript:alert(1);</script>', + '<script\\x2Ftype="text/javascript">javascript:alert(1);</script>', + '<script\\x0Atype="text/javascript">javascript:alert(1);</script>', + '\'`"><\\x3Cscript>javascript:alert(1)</script> ', + '\'`"><\\x00script>javascript:alert(1)</script>', + 'ABC<div style="x\\x3Aexpression(javascript:alert(1)">DEF', + 'ABC<div style="x:expression\\x5C(javascript:alert(1)">DEF', + 'ABC<div style="x:expression\\x00(javascript:alert(1)">DEF', + 'ABC<div style="x:exp\\x00ression(javascript:alert(1)">DEF', + 'ABC<div style="x:exp\\x5Cression(javascript:alert(1)">DEF', + 'ABC<div style="x:\\x0Aexpression(javascript:alert(1)">DEF', + 'ABC<div style="x:\\x09expression(javascript:alert(1)">DEF', + 'ABC<div style="x:\\xE3\\x80\\x80expression(javascript:alert(1)">DEF', + 'ABC<div style="x:\\xE2\\x80\\x84expression(javascript:alert(1)">DEF', + 'ABC<div style="x:\\xC2\\xA0expression(javascript:alert(1)">DEF', + 'ABC<div style="x:\\xE2\\x80\\x80expression(javascript:alert(1)">DEF', + 'ABC<div style="x:\\xE2\\x80\\x8Aexpression(javascript:alert(1)">DEF', + 'ABC<div style="x:\\x0Dexpression(javascript:alert(1)">DEF', + 'ABC<div style="x:\\x0Cexpression(javascript:alert(1)">DEF', + 'ABC<div style="x:\\xE2\\x80\\x87expression(javascript:alert(1)">DEF', + 'ABC<div style="x:\\xEF\\xBB\\xBFexpression(javascript:alert(1)">DEF', + 'ABC<div style="x:\\x20expression(javascript:alert(1)">DEF', + 'ABC<div style="x:\\xE2\\x80\\x88expression(javascript:alert(1)">DEF', + 'ABC<div style="x:\\x00expression(javascript:alert(1)">DEF', + 'ABC<div style="x:\\xE2\\x80\\x8Bexpression(javascript:alert(1)">DEF', + 'ABC<div style="x:\\xE2\\x80\\x86expression(javascript:alert(1)">DEF', + 'ABC<div style="x:\\xE2\\x80\\x85expression(javascript:alert(1)">DEF', + 'ABC<div style="x:\\xE2\\x80\\x82expression(javascript:alert(1)">DEF', + 'ABC<div style="x:\\x0Bexpression(javascript:alert(1)">DEF', + 'ABC<div style="x:\\xE2\\x80\\x81expression(javascript:alert(1)">DEF', + 'ABC<div style="x:\\xE2\\x80\\x83expression(javascript:alert(1)">DEF', + 'ABC<div style="x:\\xE2\\x80\\x89expression(javascript:alert(1)">DEF', + '<a href="\\x0Bjavascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x0Fjavascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\xC2\\xA0javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x05javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\xE1\\xA0\\x8Ejavascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x18javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x11javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\xE2\\x80\\x88javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\xE2\\x80\\x89javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\xE2\\x80\\x80javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x17javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x03javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x0Ejavascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x1Ajavascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x00javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x10javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\xE2\\x80\\x82javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x20javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x13javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x09javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\xE2\\x80\\x8Ajavascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x14javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x19javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\xE2\\x80\\xAFjavascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x1Fjavascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\xE2\\x80\\x81javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x1Djavascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\xE2\\x80\\x87javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x07javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\xE1\\x9A\\x80javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\xE2\\x80\\x83javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x04javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x01javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x08javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\xE2\\x80\\x84javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\xE2\\x80\\x86javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\xE3\\x80\\x80javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x12javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x0Djavascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x0Ajavascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x0Cjavascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x15javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\xE2\\x80\\xA8javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x16javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x02javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x1Bjavascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x06javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\xE2\\x80\\xA9javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\xE2\\x80\\x85javascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x1Ejavascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\xE2\\x81\\x9Fjavascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="\\x1Cjavascript:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="javascript\\x00:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="javascript\\x3A:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="javascript\\x09:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="javascript\\x0D:javascript:alert(1)" id="fuzzelement1">test</a>', + '<a href="javascript\\x0A:javascript:alert(1)" id="fuzzelement1">test</a>', + '`"\'><img src=xxx:x \\x0Aonerror=javascript:alert(1)>', + '`"\'><img src=xxx:x \\x22onerror=javascript:alert(1)>', + '`"\'><img src=xxx:x \\x0Bonerror=javascript:alert(1)>', + '`"\'><img src=xxx:x \\x0Donerror=javascript:alert(1)>', + '`"\'><img src=xxx:x \\x2Fonerror=javascript:alert(1)>', + '`"\'><img src=xxx:x \\x09onerror=javascript:alert(1)>', + '`"\'><img src=xxx:x \\x0Conerror=javascript:alert(1)>', + '`"\'><img src=xxx:x \\x00onerror=javascript:alert(1)>', + '`"\'><img src=xxx:x \\x27onerror=javascript:alert(1)>', + '`"\'><img src=xxx:x \\x20onerror=javascript:alert(1)>', + '"`\'><script>\\x3Bjavascript:alert(1)</script>', + '"`\'><script>\\x0Djavascript:alert(1)</script>', + '"`\'><script>\\xEF\\xBB\\xBFjavascript:alert(1)</script>', + '"`\'><script>\\xE2\\x80\\x81javascript:alert(1)</script>', + '"`\'><script>\\xE2\\x80\\x84javascript:alert(1)</script>', + '"`\'><script>\\xE3\\x80\\x80javascript:alert(1)</script>', + '"`\'><script>\\x09javascript:alert(1)</script>', + '"`\'><script>\\xE2\\x80\\x89javascript:alert(1)</script>', + '"`\'><script>\\xE2\\x80\\x85javascript:alert(1)</script>', + '"`\'><script>\\xE2\\x80\\x88javascript:alert(1)</script>', + '"`\'><script>\\x00javascript:alert(1)</script>', + '"`\'><script>\\xE2\\x80\\xA8javascript:alert(1)</script>', + '"`\'><script>\\xE2\\x80\\x8Ajavascript:alert(1)</script>', + '"`\'><script>\\xE1\\x9A\\x80javascript:alert(1)</script>', + '"`\'><script>\\x0Cjavascript:alert(1)</script>', + '"`\'><script>\\x2Bjavascript:alert(1)</script>', + '"`\'><script>\\xF0\\x90\\x96\\x9Ajavascript:alert(1)</script>', + '"`\'><script>-javascript:alert(1)</script>', + '"`\'><script>\\x0Ajavascript:alert(1)</script>', + '"`\'><script>\\xE2\\x80\\xAFjavascript:alert(1)</script>', + '"`\'><script>\\x7Ejavascript:alert(1)</script>', + '"`\'><script>\\xE2\\x80\\x87javascript:alert(1)</script>', + '"`\'><script>\\xE2\\x81\\x9Fjavascript:alert(1)</script>', + '"`\'><script>\\xE2\\x80\\xA9javascript:alert(1)</script>', + '"`\'><script>\\xC2\\x85javascript:alert(1)</script>', + '"`\'><script>\\xEF\\xBF\\xAEjavascript:alert(1)</script>', + '"`\'><script>\\xE2\\x80\\x83javascript:alert(1)</script>', + '"`\'><script>\\xE2\\x80\\x8Bjavascript:alert(1)</script>', + '"`\'><script>\\xEF\\xBF\\xBEjavascript:alert(1)</script>', + '"`\'><script>\\xE2\\x80\\x80javascript:alert(1)</script>', + '"`\'><script>\\x21javascript:alert(1)</script>', + '"`\'><script>\\xE2\\x80\\x82javascript:alert(1)</script>', + '"`\'><script>\\xE2\\x80\\x86javascript:alert(1)</script>', + '"`\'><script>\\xE1\\xA0\\x8Ejavascript:alert(1)</script>', + '"`\'><script>\\x0Bjavascript:alert(1)</script>', + '"`\'><script>\\x20javascript:alert(1)</script>', + '"`\'><script>\\xC2\\xA0javascript:alert(1)</script>', + '<img \\x00src=x onerror="alert(1)">', + '<img \\x47src=x onerror="javascript:alert(1)">', + '<img \\x11src=x onerror="javascript:alert(1)">', + '<img \\x12src=x onerror="javascript:alert(1)">', + '<img\\x47src=x onerror="javascript:alert(1)">', + '<img\\x10src=x onerror="javascript:alert(1)">', + '<img\\x13src=x onerror="javascript:alert(1)">', + '<img\\x32src=x onerror="javascript:alert(1)">', + '<img\\x47src=x onerror="javascript:alert(1)">', + '<img\\x11src=x onerror="javascript:alert(1)">', + '<img \\x47src=x onerror="javascript:alert(1)">', + '<img \\x34src=x onerror="javascript:alert(1)">', + '<img \\x39src=x onerror="javascript:alert(1)">', + '<img \\x00src=x onerror="javascript:alert(1)">', + '<img src\\x09=x onerror="javascript:alert(1)">', + '<img src\\x10=x onerror="javascript:alert(1)">', + '<img src\\x13=x onerror="javascript:alert(1)">', + '<img src\\x32=x onerror="javascript:alert(1)">', + '<img src\\x12=x onerror="javascript:alert(1)">', + '<img src\\x11=x onerror="javascript:alert(1)">', + '<img src\\x00=x onerror="javascript:alert(1)">', + '<img src\\x47=x onerror="javascript:alert(1)">', + '<img src=x\\x09onerror="javascript:alert(1)">', + '<img src=x\\x10onerror="javascript:alert(1)">', + '<img src=x\\x11onerror="javascript:alert(1)">', + '<img src=x\\x12onerror="javascript:alert(1)">', + '<img src=x\\x13onerror="javascript:alert(1)">', + '<img[a][b][c]src[d]=x[e]onerror=[f]"alert(1)">', + '<img src=x onerror=\\x09"javascript:alert(1)">', + '<img src=x onerror=\\x10"javascript:alert(1)">', + '<img src=x onerror=\\x11"javascript:alert(1)">', + '<img src=x onerror=\\x12"javascript:alert(1)">', + '<img src=x onerror=\\x32"javascript:alert(1)">', + '<img src=x onerror=\\x00"javascript:alert(1)">', + '<a href=java script:javascript:alert(1)>XXX</a>', + '<img src="x` `<script>javascript:alert(1)</script>"` `>', + '<img src onerror /" \'"= alt=javascript:alert(1)//">', + '<title onpropertychange=javascript:alert(1)>', + '<a href=http://foo.bar/#x=`y></a><img alt="`><img src=x:x onerror=javascript:alert(1)></a>">', + '<!--[if]><script>javascript:alert(1)</script -->', + '<!--[if<img src=x onerror=javascript:alert(1)//]> -->', + '<script src="/\\%(jscript)s"></script>', + '<script src="\\\\%(jscript)s"></script>', + '<IMG """><SCRIPT>alert("XSS")</SCRIPT>">', + '<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>', + '<IMG SRC=# onmouseover="alert(\'xxs\')">', + '<IMG SRC= onmouseover="alert(\'xxs\')">', + '<IMG onmouseover="alert(\'xxs\')">', + '<IMG SRC=javascript:alert('XSS')>', + '<IMG SRC=javascript:alert('XSS')>', + '<IMG SRC=javascript:alert('XSS')>', + '<IMG SRC="jav ascript:alert(\'XSS\');">', + '<IMG SRC="jav ascript:alert(\'XSS\');">', + '<IMG SRC="jav ascript:alert(\'XSS\');">', + '<IMG SRC="jav ascript:alert(\'XSS\');">', + 'perl -e \'print "<IMG SRC=java\\0script:alert(\\"XSS\\")>";\' > out', + '<IMG SRC="  javascript:alert(\'XSS\');">', + '<SCRIPT/XSS SRC="http://ha.ckers.org/xss.js"></SCRIPT>', + '<BODY onload!#$%&()*~+-_.,:;?@[/|\\]^`=alert("XSS")>', + '<SCRIPT/SRC="http://ha.ckers.org/xss.js"></SCRIPT>', + '<<SCRIPT>alert("XSS");//<</SCRIPT>', + '<SCRIPT SRC=http://ha.ckers.org/xss.js?< B >', + '<SCRIPT SRC=//ha.ckers.org/.j>', + '<IMG SRC="javascript:alert(\'XSS\')"', + '<iframe src=http://ha.ckers.org/scriptlet.html <', + "\\\";alert('XSS');//", + '<plaintext>', + '1;DROP TABLE users', + "1'; DROP TABLE users-- 1", + "' OR 1=1 -- 1", + "' OR '1'='1", + '-', + '--', + '--version', + '--help', + '$USER', + '/dev/null; touch /tmp/blns.fail ; echo', + '`touch /tmp/blns.fail`', + '$(touch /tmp/blns.fail)', + '@{[system "touch /tmp/blns.fail"]}', + 'eval("puts \'hello world\'")', + 'System("ls -al /")', + '`ls -al /`', + 'Kernel.exec("ls -al /")', + 'Kernel.exit(1)', + "%x('ls -al /')", + '<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE foo [ <!ELEMENT foo ANY ><!ENTITY xxe SYSTEM "file:///etc/passwd" >]><foo>&xxe;</foo>', + '$HOME', + "$ENV{'HOME'}", + '%d', + '%s', + '%*.*s', + '../../../../../../../../../../../etc/passwd%00', + '../../../../../../../../../../../etc/hosts', + '() { 0; }; touch /tmp/blns.shellshock1.fail;', + '() { _; } >_[$($())] { touch /tmp/blns.shellshock2.fail; }', + 'CON', + 'PRN', + 'AUX', + 'CLOCK$', + 'NUL', + 'A:', + 'ZZ:', + 'COM1', + 'LPT1', + 'LPT2', + 'LPT3', + 'COM2', + 'COM3', + 'COM4', + 'Scunthorpe General Hospital', + 'Penistone Community Church', + 'Lightwater Country Park', + 'Jimmy Clitheroe', + 'Horniman Museum', + 'shitake mushrooms', + 'RomansInSussex.co.uk', + 'http://www.cum.qc.ca/', + 'Craig Cockburn, Software Specialist', + 'Linda Callahan', + 'Dr. Herman I. Libshitz', + 'magna cum laude', + 'Super Bowl XXX', + 'medieval erection of parapets', + 'evaluate', + 'mocha', + 'expression', + 'Arsenal canal', + 'classic', + 'Tyson Gay', + "If you're reading this, you've been in a coma for almost 20 years now. We're trying a new technique. We don't know where this message will end up in your dream, but we hope it works. Please wake up, we miss you.", + 'Roses are \u001b[0;31mred\u001b[0m, violets are \u001b[0;34mblue. Hope you enjoy terminal hue', + 'But now...\u001b[20Cfor my greatest trick...\u001b[8m', + 'The quic\b\b\b\b\b\bk brown fo\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007\u0007x... [Beeeep]', + 'Powerلُلُصّبُلُلصّبُررً ॣ ॣh ॣ ॣ冗' + ], + ranges: {}, + version: 2 + } + return DocstoreClient.createDoc( + this.project_id, + this.doc._id, + this.doc.lines, + this.doc.version, + this.doc.ranges, + error => { + if (error != null) { + throw error + } + return DocstoreClient.archiveAllDoc(this.project_id, (error, res) => { + this.res = res + if (error != null) { + throw error + } + return done() + }) + } + ) + }) + + it('should successully archive the docs', function(done) { + this.res.statusCode.should.equal(204) + return done() + }) + + it('should set inS3 and unset lines and ranges in each doc', function(done) { + return db.docs.findOne({ _id: this.doc._id }, (error, doc) => { + if (error != null) { + throw error + } + should.not.exist(doc.lines) + should.not.exist(doc.ranges) + doc.inS3.should.equal(true) + return done() + }) + }) + + it('should set the doc in s3 correctly', function(done) { + return DocstoreClient.getS3Doc( + this.project_id, + this.doc._id, + (error, res, s3_doc) => { + if (error != null) { + throw error + } + s3_doc.lines.should.deep.equal(this.doc.lines) + s3_doc.ranges.should.deep.equal(this.doc.ranges) + return done() + } + ) + }) + + return describe('after unarchiving from a request for the project', function() { + before(function(done) { + return DocstoreClient.getAllDocs( + this.project_id, + (error, res, fetched_docs) => { + this.fetched_docs = fetched_docs + if (error != null) { + throw error + } + return done() + } + ) + }) + + return it('should restore the doc to mongo', function(done) { + return db.docs.findOne({ _id: this.doc._id }, (error, doc) => { + if (error != null) { + throw error + } + doc.lines.should.deep.equal(this.doc.lines) + doc.ranges.should.deep.equal(this.doc.ranges) + should.not.exist(doc.inS3) + return done() + }) + }) + }) + }) + + describe('a doc with ranges', function() { + before(function(done) { + this.project_id = ObjectId() + this.doc = { + _id: ObjectId(), + lines: ['one', 'two', 'three'], + ranges: { + changes: [ + { + id: ObjectId(), + op: { i: 'foo', p: 24 }, + metadata: { + user_id: ObjectId(), + ts: new Date('2017-01-27T16:10:44.194Z') + } + }, + { + id: ObjectId(), + op: { d: 'bar', p: 50 }, + metadata: { + user_id: ObjectId(), + ts: new Date('2017-01-27T18:10:44.194Z') + } + } + ], + comments: [ + { + id: ObjectId(), + op: { c: 'comment', p: 284, t: ObjectId() }, + metadata: { + user_id: ObjectId(), + ts: new Date('2017-01-26T14:22:04.869Z') + } + } + ] + }, + version: 2 + } + return DocstoreClient.createDoc( + this.project_id, + this.doc._id, + this.doc.lines, + this.doc.version, + this.doc.ranges, + error => { + if (error != null) { + throw error + } + return DocstoreClient.archiveAllDoc(this.project_id, (error, res) => { + this.res = res + if (error != null) { + throw error + } + return done() + }) + } + ) + }) + + it('should successully archive the docs', function(done) { + this.res.statusCode.should.equal(204) + return done() + }) + + it('should set inS3 and unset lines and ranges in each doc', function(done) { + return db.docs.findOne({ _id: this.doc._id }, (error, doc) => { + if (error != null) { + throw error + } + should.not.exist(doc.lines) + should.not.exist(doc.ranges) + doc.inS3.should.equal(true) + return done() + }) + }) + + it('should set the doc in s3 correctly', function(done) { + return DocstoreClient.getS3Doc( + this.project_id, + this.doc._id, + (error, res, s3_doc) => { + if (error != null) { + throw error + } + s3_doc.lines.should.deep.equal(this.doc.lines) + const ranges = JSON.parse(JSON.stringify(this.doc.ranges)) // ObjectId -> String + s3_doc.ranges.should.deep.equal(ranges) + return done() + } + ) + }) + + return describe('after unarchiving from a request for the project', function() { + before(function(done) { + return DocstoreClient.getAllDocs( + this.project_id, + (error, res, fetched_docs) => { + this.fetched_docs = fetched_docs + if (error != null) { + throw error + } + return done() + } + ) + }) + + return it('should restore the doc to mongo', function(done) { + return db.docs.findOne({ _id: this.doc._id }, (error, doc) => { + if (error != null) { + throw error + } + doc.lines.should.deep.equal(this.doc.lines) + doc.ranges.should.deep.equal(this.doc.ranges) + should.not.exist(doc.inS3) + return done() + }) + }) + }) + }) + + describe('a doc that is archived twice', function() { + before(function(done) { + this.project_id = ObjectId() + this.doc = { + _id: ObjectId(), + lines: ['abc', 'def', 'ghi'], + ranges: {}, + version: 2 + } + return DocstoreClient.createDoc( + this.project_id, + this.doc._id, + this.doc.lines, + this.doc.version, + this.doc.ranges, + error => { + if (error != null) { + throw error + } + return DocstoreClient.archiveAllDoc(this.project_id, (error, res) => { + this.res = res + if (error != null) { + throw error + } + this.res.statusCode.should.equal(204) + return DocstoreClient.archiveAllDoc( + this.project_id, + (error, res1) => { + this.res = res1 + if (error != null) { + throw error + } + this.res.statusCode.should.equal(204) + return done() + } + ) + }) + } + ) + }) + + it('should set inS3 and unset lines and ranges in each doc', function(done) { + return db.docs.findOne({ _id: this.doc._id }, (error, doc) => { + if (error != null) { + throw error + } + should.not.exist(doc.lines) + should.not.exist(doc.ranges) + doc.inS3.should.equal(true) + return done() + }) + }) + + it('should set the doc in s3 correctly', function(done) { + return DocstoreClient.getS3Doc( + this.project_id, + this.doc._id, + (error, res, s3_doc) => { + if (error != null) { + throw error + } + s3_doc.lines.should.deep.equal(this.doc.lines) + s3_doc.ranges.should.deep.equal(this.doc.ranges) + return done() + } + ) + }) + + return describe('after unarchiving from a request for the project', function() { + before(function(done) { + return DocstoreClient.getAllDocs( + this.project_id, + (error, res, fetched_docs) => { + this.fetched_docs = fetched_docs + if (error != null) { + throw error + } + return done() + } + ) + }) + + return it('should restore the doc to mongo', function(done) { + return db.docs.findOne({ _id: this.doc._id }, (error, doc) => { + if (error != null) { + throw error + } + doc.lines.should.deep.equal(this.doc.lines) + doc.ranges.should.deep.equal(this.doc.ranges) + should.not.exist(doc.inS3) + return done() + }) + }) + }) + }) + + return describe('a doc with the old schema (just an array of lines)', function() { + before(function(done) { + this.project_id = ObjectId() + this.doc = { + _id: ObjectId(), + lines: ['abc', 'def', 'ghi'], + ranges: {}, + version: 2 + } + const options = DocArchiveManager.buildS3Options( + `${this.project_id}/${this.doc._id}` + ) + options.json = this.doc.lines + return request.put(options, (error, res, body) => { + if (error != null) { + throw error + } + res.statusCode.should.equal(200) + return db.docs.insert( + { + project_id: this.project_id, + _id: this.doc._id, + rev: this.doc.version, + inS3: true + }, + error => { + if (error != null) { + throw error + } + return DocstoreClient.getAllDocs( + this.project_id, + (error, res, fetched_docs) => { + this.fetched_docs = fetched_docs + if (error != null) { + throw error + } + return done() + } + ) + } + ) + }) + }) + + it('should restore the doc to mongo', function(done) { + return db.docs.findOne({ _id: this.doc._id }, (error, doc) => { + if (error != null) { + throw error + } + doc.lines.should.deep.equal(this.doc.lines) + should.not.exist(doc.inS3) + return done() + }) + }) + + return it('should return the doc', function(done) { + this.fetched_docs[0].lines.should.deep.equal(this.doc.lines) + return done() + }) + }) +}) diff --git a/services/docstore/test/acceptance/js/DeletingDocsTests.js b/services/docstore/test/acceptance/js/DeletingDocsTests.js index 026730205d..8941567359 100644 --- a/services/docstore/test/acceptance/js/DeletingDocsTests.js +++ b/services/docstore/test/acceptance/js/DeletingDocsTests.js @@ -11,119 +11,149 @@ * DS207: Consider shorter variations of null checks * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const sinon = require("sinon"); -const chai = require("chai"); -chai.should(); -const {db, ObjectId} = require("../../../app/js/mongojs"); -const { - expect -} = chai; -const DocstoreApp = require("./helpers/DocstoreApp"); +const sinon = require('sinon') +const chai = require('chai') +chai.should() +const { db, ObjectId } = require('../../../app/js/mongojs') +const { expect } = chai +const DocstoreApp = require('./helpers/DocstoreApp') -const DocstoreClient = require("./helpers/DocstoreClient"); +const DocstoreClient = require('./helpers/DocstoreClient') -describe("Deleting a doc", function() { - beforeEach(function(done) { - this.project_id = ObjectId(); - this.doc_id = ObjectId(); - this.lines = ["original", "lines"]; - this.version = 42; - this.ranges = []; - return DocstoreApp.ensureRunning(() => { - return DocstoreClient.createDoc(this.project_id, this.doc_id, this.lines, this.version, this.ranges, error => { - if (error != null) { throw error; } - return done(); - }); - }); - }); +describe('Deleting a doc', function() { + beforeEach(function(done) { + this.project_id = ObjectId() + this.doc_id = ObjectId() + this.lines = ['original', 'lines'] + this.version = 42 + this.ranges = [] + return DocstoreApp.ensureRunning(() => { + return DocstoreClient.createDoc( + this.project_id, + this.doc_id, + this.lines, + this.version, + this.ranges, + error => { + if (error != null) { + throw error + } + return done() + } + ) + }) + }) - describe("when the doc exists", function() { - beforeEach(function(done) { - return DocstoreClient.deleteDoc(this.project_id, this.doc_id, (error, res, doc) => { - this.res = res; - return done(); - }); - }); + describe('when the doc exists', function() { + beforeEach(function(done) { + return DocstoreClient.deleteDoc( + this.project_id, + this.doc_id, + (error, res, doc) => { + this.res = res + return done() + } + ) + }) - afterEach(function(done) { - return db.docs.remove({_id: this.doc_id}, done); - }); + afterEach(function(done) { + return db.docs.remove({ _id: this.doc_id }, done) + }) - return it("should insert a deleted doc into the docs collection", function(done) { - return db.docs.find({_id: this.doc_id}, (error, docs) => { - docs[0]._id.should.deep.equal(this.doc_id); - docs[0].lines.should.deep.equal(this.lines); - docs[0].deleted.should.equal(true); - return done(); - }); - }); - }); + return it('should insert a deleted doc into the docs collection', function(done) { + return db.docs.find({ _id: this.doc_id }, (error, docs) => { + docs[0]._id.should.deep.equal(this.doc_id) + docs[0].lines.should.deep.equal(this.lines) + docs[0].deleted.should.equal(true) + return done() + }) + }) + }) - return describe("when the doc does not exist", function() { return it("should return a 404", function(done) { - const missing_doc_id = ObjectId(); - return DocstoreClient.deleteDoc(this.project_id, missing_doc_id, (error, res, doc) => { - res.statusCode.should.equal(404); - return done(); - }); - }); }); -}); + return describe('when the doc does not exist', function() { + return it('should return a 404', function(done) { + const missing_doc_id = ObjectId() + return DocstoreClient.deleteDoc( + this.project_id, + missing_doc_id, + (error, res, doc) => { + res.statusCode.should.equal(404) + return done() + } + ) + }) + }) +}) describe("Destroying a project's documents", function() { - describe("when the doc exists", function() { - beforeEach(function(done) { - return db.docOps.insert({doc_id: ObjectId(this.doc_id), version: 1}, function(err) { - if (err != null) { return done(err); } - return DocstoreClient.destroyAllDoc(this.project_id, done); - }); - }); + describe('when the doc exists', function() { + beforeEach(function(done) { + return db.docOps.insert( + { doc_id: ObjectId(this.doc_id), version: 1 }, + function(err) { + if (err != null) { + return done(err) + } + return DocstoreClient.destroyAllDoc(this.project_id, done) + } + ) + }) - it("should remove the doc from the docs collection", function(done) { - return db.docs.find({_id: this.doc_id}, (err, docs) => { - expect(err).not.to.exist; - expect(docs).to.deep.equal([]); - return done(); - }); - }); + it('should remove the doc from the docs collection', function(done) { + return db.docs.find({ _id: this.doc_id }, (err, docs) => { + expect(err).not.to.exist + expect(docs).to.deep.equal([]) + return done() + }) + }) - return it("should remove the docOps from the docOps collection", function(done) { - return db.docOps.find({doc_id: this.doc_id}, (err, docOps) => { - expect(err).not.to.exist; - expect(docOps).to.deep.equal([]); - return done(); - }); - }); - }); + return it('should remove the docOps from the docOps collection', function(done) { + return db.docOps.find({ doc_id: this.doc_id }, (err, docOps) => { + expect(err).not.to.exist + expect(docOps).to.deep.equal([]) + return done() + }) + }) + }) - return describe("when the doc is archived", function() { - beforeEach(function(done) { - return DocstoreClient.archiveAllDoc(this.project_id, function(err) { - if (err != null) { return done(err); } - return DocstoreClient.destroyAllDoc(this.project_id, done); - }); - }); + return describe('when the doc is archived', function() { + beforeEach(function(done) { + return DocstoreClient.archiveAllDoc(this.project_id, function(err) { + if (err != null) { + return done(err) + } + return DocstoreClient.destroyAllDoc(this.project_id, done) + }) + }) - it("should remove the doc from the docs collection", function(done) { - return db.docs.find({_id: this.doc_id}, (err, docs) => { - expect(err).not.to.exist; - expect(docs).to.deep.equal([]); - return done(); - }); - }); + it('should remove the doc from the docs collection', function(done) { + return db.docs.find({ _id: this.doc_id }, (err, docs) => { + expect(err).not.to.exist + expect(docs).to.deep.equal([]) + return done() + }) + }) - it("should remove the docOps from the docOps collection", function(done) { - return db.docOps.find({doc_id: this.doc_id}, (err, docOps) => { - expect(err).not.to.exist; - expect(docOps).to.deep.equal([]); - return done(); - }); - }); + it('should remove the docOps from the docOps collection', function(done) { + return db.docOps.find({ doc_id: this.doc_id }, (err, docOps) => { + expect(err).not.to.exist + expect(docOps).to.deep.equal([]) + return done() + }) + }) - return it("should remove the doc contents from s3", function(done) { - return DocstoreClient.getS3Doc(this.project_id, this.doc_id, (error, res, s3_doc) => { - if (error != null) { throw error; } - expect(res.statusCode).to.equal(404); - return done(); - }); - }); - }); -}); + return it('should remove the doc contents from s3', function(done) { + return DocstoreClient.getS3Doc( + this.project_id, + this.doc_id, + (error, res, s3_doc) => { + if (error != null) { + throw error + } + expect(res.statusCode).to.equal(404) + return done() + } + ) + }) + }) +}) diff --git a/services/docstore/test/acceptance/js/GettingAllDocsTests.js b/services/docstore/test/acceptance/js/GettingAllDocsTests.js index 2970042480..4fc7f811d8 100644 --- a/services/docstore/test/acceptance/js/GettingAllDocsTests.js +++ b/services/docstore/test/acceptance/js/GettingAllDocsTests.js @@ -11,79 +11,104 @@ * DS207: Consider shorter variations of null checks * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const sinon = require("sinon"); -const chai = require("chai"); -chai.should(); -const {ObjectId} = require("mongojs"); -const async = require("async"); -const DocstoreApp = require("./helpers/DocstoreApp"); +const sinon = require('sinon') +const chai = require('chai') +chai.should() +const { ObjectId } = require('mongojs') +const async = require('async') +const DocstoreApp = require('./helpers/DocstoreApp') -const DocstoreClient = require("./helpers/DocstoreClient"); +const DocstoreClient = require('./helpers/DocstoreClient') -describe("Getting all docs", function() { - beforeEach(function(done) { - this.project_id = ObjectId(); - this.docs = [{ - _id: ObjectId(), - lines: ["one", "two", "three"], - ranges: {"mock": "one"}, - rev: 2 - }, { - _id: ObjectId(), - lines: ["aaa", "bbb", "ccc"], - ranges: {"mock": "two"}, - rev: 4 - }, { - _id: ObjectId(), - lines: ["111", "222", "333"], - ranges: {"mock": "three"}, - rev: 6 - }]; - this.deleted_doc = { - _id: ObjectId(), - lines: ["deleted"], - ranges: {"mock": "four"}, - rev: 8 - }; - const version = 42; - const jobs = Array.from(this.docs).map((doc) => - (doc => { - return callback => { - return DocstoreClient.createDoc(this.project_id, doc._id, doc.lines, version, doc.ranges, callback); - }; - })(doc)); - jobs.push(cb => { - return DocstoreClient.createDoc(this.project_id, this.deleted_doc._id, this.deleted_doc.lines, version, this.deleted_doc.ranges, err=> { - return DocstoreClient.deleteDoc(this.project_id, this.deleted_doc._id, cb); - }); - }); - jobs.unshift(cb => DocstoreApp.ensureRunning(cb)); - return async.series(jobs, done); - }); - - it("getAllDocs should return all the (non-deleted) docs", function(done) { - return DocstoreClient.getAllDocs(this.project_id, (error, res, docs) => { - if (error != null) { throw error; } - docs.length.should.equal(this.docs.length); - for (let i = 0; i < docs.length; i++) { - const doc = docs[i]; - doc.lines.should.deep.equal(this.docs[i].lines); - } - return done(); - }); - }); - - return it("getAllRanges should return all the (non-deleted) doc ranges", function(done) { - return DocstoreClient.getAllRanges(this.project_id, (error, res, docs) => { - if (error != null) { throw error; } - docs.length.should.equal(this.docs.length); - for (let i = 0; i < docs.length; i++) { - const doc = docs[i]; - doc.ranges.should.deep.equal(this.docs[i].ranges); - } - return done(); - }); - }); -}); +describe('Getting all docs', function() { + beforeEach(function(done) { + this.project_id = ObjectId() + this.docs = [ + { + _id: ObjectId(), + lines: ['one', 'two', 'three'], + ranges: { mock: 'one' }, + rev: 2 + }, + { + _id: ObjectId(), + lines: ['aaa', 'bbb', 'ccc'], + ranges: { mock: 'two' }, + rev: 4 + }, + { + _id: ObjectId(), + lines: ['111', '222', '333'], + ranges: { mock: 'three' }, + rev: 6 + } + ] + this.deleted_doc = { + _id: ObjectId(), + lines: ['deleted'], + ranges: { mock: 'four' }, + rev: 8 + } + const version = 42 + const jobs = Array.from(this.docs).map(doc => + (doc => { + return callback => { + return DocstoreClient.createDoc( + this.project_id, + doc._id, + doc.lines, + version, + doc.ranges, + callback + ) + } + })(doc) + ) + jobs.push(cb => { + return DocstoreClient.createDoc( + this.project_id, + this.deleted_doc._id, + this.deleted_doc.lines, + version, + this.deleted_doc.ranges, + err => { + return DocstoreClient.deleteDoc( + this.project_id, + this.deleted_doc._id, + cb + ) + } + ) + }) + jobs.unshift(cb => DocstoreApp.ensureRunning(cb)) + return async.series(jobs, done) + }) + it('getAllDocs should return all the (non-deleted) docs', function(done) { + return DocstoreClient.getAllDocs(this.project_id, (error, res, docs) => { + if (error != null) { + throw error + } + docs.length.should.equal(this.docs.length) + for (let i = 0; i < docs.length; i++) { + const doc = docs[i] + doc.lines.should.deep.equal(this.docs[i].lines) + } + return done() + }) + }) + return it('getAllRanges should return all the (non-deleted) doc ranges', function(done) { + return DocstoreClient.getAllRanges(this.project_id, (error, res, docs) => { + if (error != null) { + throw error + } + docs.length.should.equal(this.docs.length) + for (let i = 0; i < docs.length; i++) { + const doc = docs[i] + doc.ranges.should.deep.equal(this.docs[i].ranges) + } + return done() + }) + }) +}) diff --git a/services/docstore/test/acceptance/js/GettingDocsTests.js b/services/docstore/test/acceptance/js/GettingDocsTests.js index e6a96d0958..fb3df8a657 100644 --- a/services/docstore/test/acceptance/js/GettingDocsTests.js +++ b/services/docstore/test/acceptance/js/GettingDocsTests.js @@ -11,80 +11,127 @@ * DS207: Consider shorter variations of null checks * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const sinon = require("sinon"); -const chai = require("chai"); -chai.should(); -const {ObjectId} = require("mongojs"); -const DocstoreApp = require("./helpers/DocstoreApp"); +const sinon = require('sinon') +const chai = require('chai') +chai.should() +const { ObjectId } = require('mongojs') +const DocstoreApp = require('./helpers/DocstoreApp') -const DocstoreClient = require("./helpers/DocstoreClient"); +const DocstoreClient = require('./helpers/DocstoreClient') -describe("Getting a doc", function() { - beforeEach(function(done) { - this.project_id = ObjectId(); - this.doc_id = ObjectId(); - this.lines = ["original", "lines"]; - this.version = 42; - this.ranges = { - changes: [{ - id: ObjectId().toString(), - op: { i: "foo", p: 3 }, - meta: { - user_id: ObjectId().toString(), - ts: new Date().toString() - } - }] - }; - return DocstoreApp.ensureRunning(() => { - return DocstoreClient.createDoc(this.project_id, this.doc_id, this.lines, this.version, this.ranges, error => { - if (error != null) { throw error; } - return done(); - }); - }); - }); +describe('Getting a doc', function() { + beforeEach(function(done) { + this.project_id = ObjectId() + this.doc_id = ObjectId() + this.lines = ['original', 'lines'] + this.version = 42 + this.ranges = { + changes: [ + { + id: ObjectId().toString(), + op: { i: 'foo', p: 3 }, + meta: { + user_id: ObjectId().toString(), + ts: new Date().toString() + } + } + ] + } + return DocstoreApp.ensureRunning(() => { + return DocstoreClient.createDoc( + this.project_id, + this.doc_id, + this.lines, + this.version, + this.ranges, + error => { + if (error != null) { + throw error + } + return done() + } + ) + }) + }) - describe("when the doc exists", function() { return it("should get the doc lines and version", function(done) { - return DocstoreClient.getDoc(this.project_id, this.doc_id, {}, (error, res, doc) => { - doc.lines.should.deep.equal(this.lines); - doc.version.should.equal(this.version); - doc.ranges.should.deep.equal(this.ranges); - return done(); - }); - }); }); + describe('when the doc exists', function() { + return it('should get the doc lines and version', function(done) { + return DocstoreClient.getDoc( + this.project_id, + this.doc_id, + {}, + (error, res, doc) => { + doc.lines.should.deep.equal(this.lines) + doc.version.should.equal(this.version) + doc.ranges.should.deep.equal(this.ranges) + return done() + } + ) + }) + }) - describe("when the doc does not exist", function() { return it("should return a 404", function(done) { - const missing_doc_id = ObjectId(); - return DocstoreClient.getDoc(this.project_id, missing_doc_id, {}, (error, res, doc) => { - res.statusCode.should.equal(404); - return done(); - }); - }); }); + describe('when the doc does not exist', function() { + return it('should return a 404', function(done) { + const missing_doc_id = ObjectId() + return DocstoreClient.getDoc( + this.project_id, + missing_doc_id, + {}, + (error, res, doc) => { + res.statusCode.should.equal(404) + return done() + } + ) + }) + }) - return describe("when the doc is a deleted doc", function() { - beforeEach(function(done) { - this.deleted_doc_id = ObjectId(); - return DocstoreClient.createDoc(this.project_id, this.deleted_doc_id, this.lines, this.version, this.ranges, error => { - if (error != null) { throw error; } - return DocstoreClient.deleteDoc(this.project_id, this.deleted_doc_id, done); - }); - }); + return describe('when the doc is a deleted doc', function() { + beforeEach(function(done) { + this.deleted_doc_id = ObjectId() + return DocstoreClient.createDoc( + this.project_id, + this.deleted_doc_id, + this.lines, + this.version, + this.ranges, + error => { + if (error != null) { + throw error + } + return DocstoreClient.deleteDoc( + this.project_id, + this.deleted_doc_id, + done + ) + } + ) + }) - it("should return the doc", function(done) { - return DocstoreClient.getDoc(this.project_id, this.deleted_doc_id, {include_deleted:true},(error, res, doc) => { - doc.lines.should.deep.equal(this.lines); - doc.version.should.equal(this.version); - doc.ranges.should.deep.equal(this.ranges); - doc.deleted.should.equal(true); - return done(); - }); - }); + it('should return the doc', function(done) { + return DocstoreClient.getDoc( + this.project_id, + this.deleted_doc_id, + { include_deleted: true }, + (error, res, doc) => { + doc.lines.should.deep.equal(this.lines) + doc.version.should.equal(this.version) + doc.ranges.should.deep.equal(this.ranges) + doc.deleted.should.equal(true) + return done() + } + ) + }) - return it("should return a 404 when the query string is not set", function(done){ - return DocstoreClient.getDoc(this.project_id, this.deleted_doc_id, {},(error, res, doc) => { - res.statusCode.should.equal(404); - return done(); - }); - }); - }); -}); - \ No newline at end of file + return it('should return a 404 when the query string is not set', function(done) { + return DocstoreClient.getDoc( + this.project_id, + this.deleted_doc_id, + {}, + (error, res, doc) => { + res.statusCode.should.equal(404) + return done() + } + ) + }) + }) +}) diff --git a/services/docstore/test/acceptance/js/UpdatingDocsTests.js b/services/docstore/test/acceptance/js/UpdatingDocsTests.js index b3908ba2c4..96f5dfac47 100644 --- a/services/docstore/test/acceptance/js/UpdatingDocsTests.js +++ b/services/docstore/test/acceptance/js/UpdatingDocsTests.js @@ -10,329 +10,490 @@ * DS207: Consider shorter variations of null checks * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const sinon = require("sinon"); -const chai = require("chai"); -chai.should(); -const {ObjectId} = require("mongojs"); -const DocstoreApp = require("./helpers/DocstoreApp"); +const sinon = require('sinon') +const chai = require('chai') +chai.should() +const { ObjectId } = require('mongojs') +const DocstoreApp = require('./helpers/DocstoreApp') -const DocstoreClient = require("./helpers/DocstoreClient"); +const DocstoreClient = require('./helpers/DocstoreClient') -describe("Applying updates to a doc", function() { - beforeEach(function(done) { - this.project_id = ObjectId(); - this.doc_id = ObjectId(); - this.originalLines = ["original", "lines"]; - this.newLines = ["new", "lines"]; - this.originalRanges = { - changes: [{ - id: ObjectId().toString(), - op: { i: "foo", p: 3 }, - meta: { - user_id: ObjectId().toString(), - ts: new Date().toString() - } - }] - }; - this.newRanges = { - changes: [{ - id: ObjectId().toString(), - op: { i: "bar", p: 6 }, - meta: { - user_id: ObjectId().toString(), - ts: new Date().toString() - } - }] - }; - this.version = 42; - return DocstoreApp.ensureRunning(() => { - return DocstoreClient.createDoc(this.project_id, this.doc_id, this.originalLines, this.version, this.originalRanges, error => { - if (error != null) { throw error; } - return done(); - }); - }); - }); +describe('Applying updates to a doc', function() { + beforeEach(function(done) { + this.project_id = ObjectId() + this.doc_id = ObjectId() + this.originalLines = ['original', 'lines'] + this.newLines = ['new', 'lines'] + this.originalRanges = { + changes: [ + { + id: ObjectId().toString(), + op: { i: 'foo', p: 3 }, + meta: { + user_id: ObjectId().toString(), + ts: new Date().toString() + } + } + ] + } + this.newRanges = { + changes: [ + { + id: ObjectId().toString(), + op: { i: 'bar', p: 6 }, + meta: { + user_id: ObjectId().toString(), + ts: new Date().toString() + } + } + ] + } + this.version = 42 + return DocstoreApp.ensureRunning(() => { + return DocstoreClient.createDoc( + this.project_id, + this.doc_id, + this.originalLines, + this.version, + this.originalRanges, + error => { + if (error != null) { + throw error + } + return done() + } + ) + }) + }) - describe("when nothing has been updated", function() { - beforeEach(function(done) { - return DocstoreClient.updateDoc(this.project_id, this.doc_id, this.originalLines, this.version, this.originalRanges, (error, res, body) => { - this.body = body; - return done(); - }); - }); + describe('when nothing has been updated', function() { + beforeEach(function(done) { + return DocstoreClient.updateDoc( + this.project_id, + this.doc_id, + this.originalLines, + this.version, + this.originalRanges, + (error, res, body) => { + this.body = body + return done() + } + ) + }) - it("should return modified = false", function() { - return this.body.modified.should.equal(false); - }); + it('should return modified = false', function() { + return this.body.modified.should.equal(false) + }) - return it("should not update the doc in the API", function(done) { - return DocstoreClient.getDoc(this.project_id, this.doc_id, {}, (error, res, doc) => { - doc.lines.should.deep.equal(this.originalLines); - doc.version.should.equal(this.version); - doc.ranges.should.deep.equal(this.originalRanges); - return done(); - }); - }); - }); + return it('should not update the doc in the API', function(done) { + return DocstoreClient.getDoc( + this.project_id, + this.doc_id, + {}, + (error, res, doc) => { + doc.lines.should.deep.equal(this.originalLines) + doc.version.should.equal(this.version) + doc.ranges.should.deep.equal(this.originalRanges) + return done() + } + ) + }) + }) - describe("when the lines have changed", function() { - beforeEach(function(done) { - return DocstoreClient.updateDoc(this.project_id, this.doc_id, this.newLines, this.version, this.originalRanges, (error, res, body) => { - this.body = body; - return done(); - }); - }); + describe('when the lines have changed', function() { + beforeEach(function(done) { + return DocstoreClient.updateDoc( + this.project_id, + this.doc_id, + this.newLines, + this.version, + this.originalRanges, + (error, res, body) => { + this.body = body + return done() + } + ) + }) - it("should return modified = true", function() { - return this.body.modified.should.equal(true); - }); + it('should return modified = true', function() { + return this.body.modified.should.equal(true) + }) - it("should return the rev", function() { - return this.body.rev.should.equal(2); - }); + it('should return the rev', function() { + return this.body.rev.should.equal(2) + }) - return it("should update the doc in the API", function(done) { - return DocstoreClient.getDoc(this.project_id, this.doc_id, {}, (error, res, doc) => { - doc.lines.should.deep.equal(this.newLines); - doc.version.should.equal(this.version); - doc.ranges.should.deep.equal(this.originalRanges); - return done(); - }); - }); - }); + return it('should update the doc in the API', function(done) { + return DocstoreClient.getDoc( + this.project_id, + this.doc_id, + {}, + (error, res, doc) => { + doc.lines.should.deep.equal(this.newLines) + doc.version.should.equal(this.version) + doc.ranges.should.deep.equal(this.originalRanges) + return done() + } + ) + }) + }) - describe("when the version has changed", function() { - beforeEach(function(done) { - return DocstoreClient.updateDoc(this.project_id, this.doc_id, this.originalLines, this.version + 1, this.originalRanges, (error, res, body) => { - this.body = body; - return done(); - }); - }); + describe('when the version has changed', function() { + beforeEach(function(done) { + return DocstoreClient.updateDoc( + this.project_id, + this.doc_id, + this.originalLines, + this.version + 1, + this.originalRanges, + (error, res, body) => { + this.body = body + return done() + } + ) + }) - it("should return modified = true", function() { - return this.body.modified.should.equal(true); - }); + it('should return modified = true', function() { + return this.body.modified.should.equal(true) + }) - it("should return the rev", function() { - return this.body.rev.should.equal(1); - }); + it('should return the rev', function() { + return this.body.rev.should.equal(1) + }) - return it("should update the doc in the API", function(done) { - return DocstoreClient.getDoc(this.project_id, this.doc_id, {}, (error, res, doc) => { - doc.lines.should.deep.equal(this.originalLines); - doc.version.should.equal(this.version + 1); - doc.ranges.should.deep.equal(this.originalRanges); - return done(); - }); - }); - }); + return it('should update the doc in the API', function(done) { + return DocstoreClient.getDoc( + this.project_id, + this.doc_id, + {}, + (error, res, doc) => { + doc.lines.should.deep.equal(this.originalLines) + doc.version.should.equal(this.version + 1) + doc.ranges.should.deep.equal(this.originalRanges) + return done() + } + ) + }) + }) - describe("when the ranges have changed", function() { - beforeEach(function(done) { - return DocstoreClient.updateDoc(this.project_id, this.doc_id, this.originalLines, this.version, this.newRanges, (error, res, body) => { - this.body = body; - return done(); - }); - }); + describe('when the ranges have changed', function() { + beforeEach(function(done) { + return DocstoreClient.updateDoc( + this.project_id, + this.doc_id, + this.originalLines, + this.version, + this.newRanges, + (error, res, body) => { + this.body = body + return done() + } + ) + }) - it("should return modified = true", function() { - return this.body.modified.should.equal(true); - }); + it('should return modified = true', function() { + return this.body.modified.should.equal(true) + }) - it("should return the rev", function() { - return this.body.rev.should.equal(2); - }); + it('should return the rev', function() { + return this.body.rev.should.equal(2) + }) - return it("should update the doc in the API", function(done) { - return DocstoreClient.getDoc(this.project_id, this.doc_id, {}, (error, res, doc) => { - doc.lines.should.deep.equal(this.originalLines); - doc.version.should.equal(this.version); - doc.ranges.should.deep.equal(this.newRanges); - return done(); - }); - }); - }); + return it('should update the doc in the API', function(done) { + return DocstoreClient.getDoc( + this.project_id, + this.doc_id, + {}, + (error, res, doc) => { + doc.lines.should.deep.equal(this.originalLines) + doc.version.should.equal(this.version) + doc.ranges.should.deep.equal(this.newRanges) + return done() + } + ) + }) + }) - describe("when the doc does not exist", function() { - beforeEach(function(done) { - this.missing_doc_id = ObjectId(); - return DocstoreClient.updateDoc(this.project_id, this.missing_doc_id, this.originalLines, 0, this.originalRanges, (error, res, body) => { - this.res = res; - this.body = body; - return done(); - }); - }); + describe('when the doc does not exist', function() { + beforeEach(function(done) { + this.missing_doc_id = ObjectId() + return DocstoreClient.updateDoc( + this.project_id, + this.missing_doc_id, + this.originalLines, + 0, + this.originalRanges, + (error, res, body) => { + this.res = res + this.body = body + return done() + } + ) + }) - it("should create the doc", function() { - return this.body.rev.should.equal(1); - }); + it('should create the doc', function() { + return this.body.rev.should.equal(1) + }) - return it("should be retreivable", function(done){ - return DocstoreClient.getDoc(this.project_id, this.missing_doc_id, {}, (error, res, doc) => { - doc.lines.should.deep.equal(this.originalLines); - doc.version.should.equal(0); - doc.ranges.should.deep.equal(this.originalRanges); - return done(); - }); - }); - }); + return it('should be retreivable', function(done) { + return DocstoreClient.getDoc( + this.project_id, + this.missing_doc_id, + {}, + (error, res, doc) => { + doc.lines.should.deep.equal(this.originalLines) + doc.version.should.equal(0) + doc.ranges.should.deep.equal(this.originalRanges) + return done() + } + ) + }) + }) - describe("when malformed doc lines are provided", function() { - describe("when the lines are not an array", function() { - beforeEach(function(done) { - return DocstoreClient.updateDoc(this.project_id, this.doc_id, { foo: "bar" }, this.version, this.originalRanges, (error, res, body) => { - this.res = res; - this.body = body; - return done(); - }); - }); + describe('when malformed doc lines are provided', function() { + describe('when the lines are not an array', function() { + beforeEach(function(done) { + return DocstoreClient.updateDoc( + this.project_id, + this.doc_id, + { foo: 'bar' }, + this.version, + this.originalRanges, + (error, res, body) => { + this.res = res + this.body = body + return done() + } + ) + }) - it("should return 400", function() { - return this.res.statusCode.should.equal(400); - }); + it('should return 400', function() { + return this.res.statusCode.should.equal(400) + }) - return it("should not update the doc in the API", function(done) { - return DocstoreClient.getDoc(this.project_id, this.doc_id, {}, (error, res, doc) => { - doc.lines.should.deep.equal(this.originalLines); - return done(); - }); - }); - }); + return it('should not update the doc in the API', function(done) { + return DocstoreClient.getDoc( + this.project_id, + this.doc_id, + {}, + (error, res, doc) => { + doc.lines.should.deep.equal(this.originalLines) + return done() + } + ) + }) + }) - return describe("when the lines are not present", function() { - beforeEach(function(done) { - return DocstoreClient.updateDoc(this.project_id, this.doc_id, null, this.version, this.originalRanges, (error, res, body) => { - this.res = res; - this.body = body; - return done(); - }); - }); + return describe('when the lines are not present', function() { + beforeEach(function(done) { + return DocstoreClient.updateDoc( + this.project_id, + this.doc_id, + null, + this.version, + this.originalRanges, + (error, res, body) => { + this.res = res + this.body = body + return done() + } + ) + }) - it("should return 400", function() { - return this.res.statusCode.should.equal(400); - }); + it('should return 400', function() { + return this.res.statusCode.should.equal(400) + }) - return it("should not update the doc in the API", function(done) { - return DocstoreClient.getDoc(this.project_id, this.doc_id, {}, (error, res, doc) => { - doc.lines.should.deep.equal(this.originalLines); - return done(); - }); - }); - }); - }); - - describe("when no version is provided", function() { - beforeEach(function(done) { - return DocstoreClient.updateDoc(this.project_id, this.doc_id, this.originalLines, null, this.originalRanges, (error, res, body) => { - this.res = res; - this.body = body; - return done(); - }); - }); + return it('should not update the doc in the API', function(done) { + return DocstoreClient.getDoc( + this.project_id, + this.doc_id, + {}, + (error, res, doc) => { + doc.lines.should.deep.equal(this.originalLines) + return done() + } + ) + }) + }) + }) - it("should return 400", function() { - return this.res.statusCode.should.equal(400); - }); + describe('when no version is provided', function() { + beforeEach(function(done) { + return DocstoreClient.updateDoc( + this.project_id, + this.doc_id, + this.originalLines, + null, + this.originalRanges, + (error, res, body) => { + this.res = res + this.body = body + return done() + } + ) + }) - return it("should not update the doc in the API", function(done) { - return DocstoreClient.getDoc(this.project_id, this.doc_id, {}, (error, res, doc) => { - doc.lines.should.deep.equal(this.originalLines); - doc.version.should.equal(this.version); - return done(); - }); - }); - }); + it('should return 400', function() { + return this.res.statusCode.should.equal(400) + }) - describe("when the content is large", function() { - beforeEach(function(done) { - const line = new Array(1025).join("x"); // 1kb - this.largeLines = Array.apply(null, Array(1024)).map(() => line); // 1mb - return DocstoreClient.updateDoc(this.project_id, this.doc_id, this.largeLines, this.version, this.originalRanges, (error, res, body) => { - this.body = body; - return done(); - }); - }); + return it('should not update the doc in the API', function(done) { + return DocstoreClient.getDoc( + this.project_id, + this.doc_id, + {}, + (error, res, doc) => { + doc.lines.should.deep.equal(this.originalLines) + doc.version.should.equal(this.version) + return done() + } + ) + }) + }) - it("should return modified = true", function() { - return this.body.modified.should.equal(true); - }); + describe('when the content is large', function() { + beforeEach(function(done) { + const line = new Array(1025).join('x') // 1kb + this.largeLines = Array.apply(null, Array(1024)).map(() => line) // 1mb + return DocstoreClient.updateDoc( + this.project_id, + this.doc_id, + this.largeLines, + this.version, + this.originalRanges, + (error, res, body) => { + this.body = body + return done() + } + ) + }) - return it("should update the doc in the API", function(done) { - return DocstoreClient.getDoc(this.project_id, this.doc_id, {}, (error, res, doc) => { - doc.lines.should.deep.equal(this.largeLines); - return done(); - }); - }); - }); + it('should return modified = true', function() { + return this.body.modified.should.equal(true) + }) - describe("when there is a large json payload", function() { - beforeEach(function(done) { - const line = new Array(1025).join("x"); // 1kb - this.largeLines = Array.apply(null, Array(1024)).map(() => line); // 1kb - this.originalRanges.padding = Array.apply(null, Array(2049)).map(() => line); // 2mb + 1kb - return DocstoreClient.updateDoc(this.project_id, this.doc_id, this.largeLines, this.version, this.originalRanges, (error, res, body) => { - this.res = res; - this.body = body; - return done(); - }); - }); + return it('should update the doc in the API', function(done) { + return DocstoreClient.getDoc( + this.project_id, + this.doc_id, + {}, + (error, res, doc) => { + doc.lines.should.deep.equal(this.largeLines) + return done() + } + ) + }) + }) - it("should return modified = true", function() { - return this.body.modified.should.equal(true); - }); + describe('when there is a large json payload', function() { + beforeEach(function(done) { + const line = new Array(1025).join('x') // 1kb + this.largeLines = Array.apply(null, Array(1024)).map(() => line) // 1kb + this.originalRanges.padding = Array.apply(null, Array(2049)).map( + () => line + ) // 2mb + 1kb + return DocstoreClient.updateDoc( + this.project_id, + this.doc_id, + this.largeLines, + this.version, + this.originalRanges, + (error, res, body) => { + this.res = res + this.body = body + return done() + } + ) + }) - return it("should update the doc in the API", function(done) { - return DocstoreClient.getDoc(this.project_id, this.doc_id, {}, (error, res, doc) => { - doc.lines.should.deep.equal(this.largeLines); - return done(); - }); - }); - }); + it('should return modified = true', function() { + return this.body.modified.should.equal(true) + }) - describe("when the document body is too large", function() { - beforeEach(function(done) { - const line = new Array(1025).join("x"); // 1kb - this.largeLines = Array.apply(null, Array(2049)).map(() => line); // 2mb + 1kb - return DocstoreClient.updateDoc(this.project_id, this.doc_id, this.largeLines, this.version, this.originalRanges, (error, res, body) => { - this.res = res; - this.body = body; - return done(); - }); - }); + return it('should update the doc in the API', function(done) { + return DocstoreClient.getDoc( + this.project_id, + this.doc_id, + {}, + (error, res, doc) => { + doc.lines.should.deep.equal(this.largeLines) + return done() + } + ) + }) + }) - it("should return 413", function() { - return this.res.statusCode.should.equal(413); - }); + describe('when the document body is too large', function() { + beforeEach(function(done) { + const line = new Array(1025).join('x') // 1kb + this.largeLines = Array.apply(null, Array(2049)).map(() => line) // 2mb + 1kb + return DocstoreClient.updateDoc( + this.project_id, + this.doc_id, + this.largeLines, + this.version, + this.originalRanges, + (error, res, body) => { + this.res = res + this.body = body + return done() + } + ) + }) - it("should report body too large", function() { - return this.res.body.should.equal('document body too large'); - }); + it('should return 413', function() { + return this.res.statusCode.should.equal(413) + }) - return it("should not update the doc in the API", function(done) { - return DocstoreClient.getDoc(this.project_id, this.doc_id, {}, (error, res, doc) => { - doc.lines.should.deep.equal(this.originalLines); - return done(); - }); - }); - }); + it('should report body too large', function() { + return this.res.body.should.equal('document body too large') + }) - return describe("when the json payload is too large", function() { - beforeEach(function(done) { - const line = new Array(1025).join("x"); // 1kb - this.largeLines = Array.apply(null, Array(1024)).map(() => line); // 1kb - this.originalRanges.padding = Array.apply(null, Array(4096)).map(() => line); // 4mb - return DocstoreClient.updateDoc(this.project_id, this.doc_id, this.largeLines, this.version, this.originalRanges, (error, res, body) => { - this.res = res; - this.body = body; - return done(); - }); - }); + return it('should not update the doc in the API', function(done) { + return DocstoreClient.getDoc( + this.project_id, + this.doc_id, + {}, + (error, res, doc) => { + doc.lines.should.deep.equal(this.originalLines) + return done() + } + ) + }) + }) - return it("should not update the doc in the API", function(done) { - return DocstoreClient.getDoc(this.project_id, this.doc_id, {}, (error, res, doc) => { - doc.lines.should.deep.equal(this.originalLines); - return done(); - }); - }); - }); -}); + return describe('when the json payload is too large', function() { + beforeEach(function(done) { + const line = new Array(1025).join('x') // 1kb + this.largeLines = Array.apply(null, Array(1024)).map(() => line) // 1kb + this.originalRanges.padding = Array.apply(null, Array(4096)).map( + () => line + ) // 4mb + return DocstoreClient.updateDoc( + this.project_id, + this.doc_id, + this.largeLines, + this.version, + this.originalRanges, + (error, res, body) => { + this.res = res + this.body = body + return done() + } + ) + }) + + return it('should not update the doc in the API', function(done) { + return DocstoreClient.getDoc( + this.project_id, + this.doc_id, + {}, + (error, res, doc) => { + doc.lines.should.deep.equal(this.originalLines) + return done() + } + ) + }) + }) +}) diff --git a/services/docstore/test/acceptance/js/helpers/DocstoreApp.js b/services/docstore/test/acceptance/js/helpers/DocstoreApp.js index 9fd8389576..e29117bd78 100644 --- a/services/docstore/test/acceptance/js/helpers/DocstoreApp.js +++ b/services/docstore/test/acceptance/js/helpers/DocstoreApp.js @@ -11,34 +11,38 @@ * DS207: Consider shorter variations of null checks * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const app = require('../../../../app'); -require("logger-sharelatex").logger.level("error"); -const settings = require("settings-sharelatex"); +const app = require('../../../../app') +require('logger-sharelatex').logger.level('error') +const settings = require('settings-sharelatex') module.exports = { - running: false, - initing: false, - callbacks: [], - ensureRunning(callback) { - if (callback == null) { callback = function(error) {}; } - if (this.running) { - return callback(); - } else if (this.initing) { - return this.callbacks.push(callback); - } else { - this.initing = true; - this.callbacks.push(callback); - return app.listen(settings.internal.docstore.port, "localhost", error => { - if (error != null) { throw error; } - this.running = true; - return (() => { - const result = []; - for (callback of Array.from(this.callbacks)) { - result.push(callback()); - } - return result; - })(); - }); - } - } -}; \ No newline at end of file + running: false, + initing: false, + callbacks: [], + ensureRunning(callback) { + if (callback == null) { + callback = function(error) {} + } + if (this.running) { + return callback() + } else if (this.initing) { + return this.callbacks.push(callback) + } else { + this.initing = true + this.callbacks.push(callback) + return app.listen(settings.internal.docstore.port, 'localhost', error => { + if (error != null) { + throw error + } + this.running = true + return (() => { + const result = [] + for (callback of Array.from(this.callbacks)) { + result.push(callback()) + } + return result + })() + }) + } + } +} diff --git a/services/docstore/test/acceptance/js/helpers/DocstoreClient.js b/services/docstore/test/acceptance/js/helpers/DocstoreClient.js index 129723a9ea..da91433880 100644 --- a/services/docstore/test/acceptance/js/helpers/DocstoreClient.js +++ b/services/docstore/test/acceptance/js/helpers/DocstoreClient.js @@ -11,81 +11,126 @@ * DS207: Consider shorter variations of null checks * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -let DocstoreClient; -const request = require("request").defaults({jar: false}); -const {db, ObjectId} = require("../../../../app/js/mongojs"); -const settings = require("settings-sharelatex"); -const DocArchiveManager = require("../../../../app/js/DocArchiveManager.js"); +let DocstoreClient +const request = require('request').defaults({ jar: false }) +const { db, ObjectId } = require('../../../../app/js/mongojs') +const settings = require('settings-sharelatex') +const DocArchiveManager = require('../../../../app/js/DocArchiveManager.js') -module.exports = (DocstoreClient = { +module.exports = DocstoreClient = { + createDoc(project_id, doc_id, lines, version, ranges, callback) { + if (callback == null) { + callback = function(error) {} + } + return DocstoreClient.updateDoc( + project_id, + doc_id, + lines, + version, + ranges, + callback + ) + }, - createDoc(project_id, doc_id, lines, version, ranges, callback) { - if (callback == null) { callback = function(error) {}; } - return DocstoreClient.updateDoc(project_id, doc_id, lines, version, ranges, callback); - }, + getDoc(project_id, doc_id, qs, callback) { + if (callback == null) { + callback = function(error, res, body) {} + } + return request.get( + { + url: `http://localhost:${settings.internal.docstore.port}/project/${project_id}/doc/${doc_id}`, + json: true, + qs + }, + callback + ) + }, - getDoc(project_id, doc_id, qs, callback) { - if (callback == null) { callback = function(error, res, body) {}; } - return request.get({ - url: `http://localhost:${settings.internal.docstore.port}/project/${project_id}/doc/${doc_id}`, - json: true, - qs - }, callback); - }, + getAllDocs(project_id, callback) { + if (callback == null) { + callback = function(error, res, body) {} + } + return request.get( + { + url: `http://localhost:${settings.internal.docstore.port}/project/${project_id}/doc`, + json: true + }, + callback + ) + }, - getAllDocs(project_id, callback) { - if (callback == null) { callback = function(error, res, body) {}; } - return request.get({ - url: `http://localhost:${settings.internal.docstore.port}/project/${project_id}/doc`, - json: true - }, callback); - }, + getAllRanges(project_id, callback) { + if (callback == null) { + callback = function(error, res, body) {} + } + return request.get( + { + url: `http://localhost:${settings.internal.docstore.port}/project/${project_id}/ranges`, + json: true + }, + callback + ) + }, - getAllRanges(project_id, callback) { - if (callback == null) { callback = function(error, res, body) {}; } - return request.get({ - url: `http://localhost:${settings.internal.docstore.port}/project/${project_id}/ranges`, - json: true - }, callback); - }, + updateDoc(project_id, doc_id, lines, version, ranges, callback) { + if (callback == null) { + callback = function(error, res, body) {} + } + return request.post( + { + url: `http://localhost:${settings.internal.docstore.port}/project/${project_id}/doc/${doc_id}`, + json: { + lines, + version, + ranges + } + }, + callback + ) + }, - updateDoc(project_id, doc_id, lines, version, ranges, callback) { - if (callback == null) { callback = function(error, res, body) {}; } - return request.post({ - url: `http://localhost:${settings.internal.docstore.port}/project/${project_id}/doc/${doc_id}`, - json: { - lines, - version, - ranges - } - }, callback); - }, + deleteDoc(project_id, doc_id, callback) { + if (callback == null) { + callback = function(error, res, body) {} + } + return request.del( + { + url: `http://localhost:${settings.internal.docstore.port}/project/${project_id}/doc/${doc_id}` + }, + callback + ) + }, - deleteDoc(project_id, doc_id, callback) { - if (callback == null) { callback = function(error, res, body) {}; } - return request.del({ - url: `http://localhost:${settings.internal.docstore.port}/project/${project_id}/doc/${doc_id}` - }, callback); - }, - - archiveAllDoc(project_id, callback) { - if (callback == null) { callback = function(error, res, body) {}; } - return request.post({ - url: `http://localhost:${settings.internal.docstore.port}/project/${project_id}/archive` - }, callback); - }, + archiveAllDoc(project_id, callback) { + if (callback == null) { + callback = function(error, res, body) {} + } + return request.post( + { + url: `http://localhost:${settings.internal.docstore.port}/project/${project_id}/archive` + }, + callback + ) + }, - destroyAllDoc(project_id, callback) { - if (callback == null) { callback = function(error, res, body) {}; } - return request.post({ - url: `http://localhost:${settings.internal.docstore.port}/project/${project_id}/destroy` - }, callback); - }, + destroyAllDoc(project_id, callback) { + if (callback == null) { + callback = function(error, res, body) {} + } + return request.post( + { + url: `http://localhost:${settings.internal.docstore.port}/project/${project_id}/destroy` + }, + callback + ) + }, - getS3Doc(project_id, doc_id, callback) { - if (callback == null) { callback = function(error, res, body) {}; } - const options = DocArchiveManager.buildS3Options(project_id+"/"+doc_id); - options.json = true; - return request.get(options, callback); - } -}); + getS3Doc(project_id, doc_id, callback) { + if (callback == null) { + callback = function(error, res, body) {} + } + const options = DocArchiveManager.buildS3Options(project_id + '/' + doc_id) + options.json = true + return request.get(options, callback) + } +} From b8aa04b9ff1182400a0a31a416461b70598cd533 Mon Sep 17 00:00:00 2001 From: Simon Detheridge <s@sd.ai> Date: Sun, 16 Feb 2020 14:03:31 +0000 Subject: [PATCH 19/27] decaffeinate: rename individual coffee files to js files --- services/docstore/{app.coffee => app.js} | 0 .../config/{settings.defaults.coffee => settings.defaults.js} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename services/docstore/{app.coffee => app.js} (100%) rename services/docstore/config/{settings.defaults.coffee => settings.defaults.js} (100%) diff --git a/services/docstore/app.coffee b/services/docstore/app.js similarity index 100% rename from services/docstore/app.coffee rename to services/docstore/app.js diff --git a/services/docstore/config/settings.defaults.coffee b/services/docstore/config/settings.defaults.js similarity index 100% rename from services/docstore/config/settings.defaults.coffee rename to services/docstore/config/settings.defaults.js From 421d6dabab5ee987cab99acdafecf02e1581c052 Mon Sep 17 00:00:00 2001 From: Simon Detheridge <s@sd.ai> Date: Sun, 16 Feb 2020 14:03:43 +0000 Subject: [PATCH 20/27] decaffeinate: convert individual files to js --- services/docstore/app.js | 121 ++++++++++-------- services/docstore/config/settings.defaults.js | 57 +++++---- 2 files changed, 105 insertions(+), 73 deletions(-) diff --git a/services/docstore/app.js b/services/docstore/app.js index c32e3a6b19..2a14168054 100644 --- a/services/docstore/app.js +++ b/services/docstore/app.js @@ -1,67 +1,86 @@ -Metrics = require "metrics-sharelatex" -Metrics.initialize("docstore") -Settings = require "settings-sharelatex" -logger = require "logger-sharelatex" -express = require "express" -bodyParser = require "body-parser" -Errors = require "./app/js/Errors" -HttpController = require "./app/js/HttpController" -Path = require "path" +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS207: Consider shorter variations of null checks + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +const Metrics = require("metrics-sharelatex"); +Metrics.initialize("docstore"); +const Settings = require("settings-sharelatex"); +const logger = require("logger-sharelatex"); +const express = require("express"); +const bodyParser = require("body-parser"); +const Errors = require("./app/js/Errors"); +const HttpController = require("./app/js/HttpController"); +const Path = require("path"); -logger.initialize("docstore") -Metrics.event_loop?.monitor(logger) +logger.initialize("docstore"); +if (Metrics.event_loop != null) { + Metrics.event_loop.monitor(logger); +} -app = express() +const app = express(); -app.use Metrics.http.monitor(logger) +app.use(Metrics.http.monitor(logger)); -Metrics.injectMetricsRoute(app) +Metrics.injectMetricsRoute(app); -app.param 'project_id', (req, res, next, project_id) -> - if project_id?.match /^[0-9a-f]{24}$/ - next() - else - next new Error("invalid project id") +app.param('project_id', function(req, res, next, project_id) { + if ((project_id != null ? project_id.match(/^[0-9a-f]{24}$/) : undefined)) { + return next(); + } else { + return next(new Error("invalid project id")); + } +}); -app.param 'doc_id', (req, res, next, doc_id) -> - if doc_id?.match /^[0-9a-f]{24}$/ - next() - else - next new Error("invalid doc id") +app.param('doc_id', function(req, res, next, doc_id) { + if ((doc_id != null ? doc_id.match(/^[0-9a-f]{24}$/) : undefined)) { + return next(); + } else { + return next(new Error("invalid doc id")); + } +}); -Metrics.injectMetricsRoute(app) +Metrics.injectMetricsRoute(app); -app.get '/project/:project_id/doc', HttpController.getAllDocs -app.get '/project/:project_id/ranges', HttpController.getAllRanges -app.get '/project/:project_id/doc/:doc_id', HttpController.getDoc -app.get '/project/:project_id/doc/:doc_id/raw', HttpController.getRawDoc -# Add 64kb overhead for the JSON encoding, and double the size to allow for ranges in the json payload -app.post '/project/:project_id/doc/:doc_id', bodyParser.json(limit: (Settings.max_doc_length + 64 * 1024) * 2), HttpController.updateDoc -app.del '/project/:project_id/doc/:doc_id', HttpController.deleteDoc +app.get('/project/:project_id/doc', HttpController.getAllDocs); +app.get('/project/:project_id/ranges', HttpController.getAllRanges); +app.get('/project/:project_id/doc/:doc_id', HttpController.getDoc); +app.get('/project/:project_id/doc/:doc_id/raw', HttpController.getRawDoc); +// Add 64kb overhead for the JSON encoding, and double the size to allow for ranges in the json payload +app.post('/project/:project_id/doc/:doc_id', bodyParser.json({limit: (Settings.max_doc_length + (64 * 1024)) * 2}), HttpController.updateDoc); +app.del('/project/:project_id/doc/:doc_id', HttpController.deleteDoc); -app.post '/project/:project_id/archive', HttpController.archiveAllDocs -app.post '/project/:project_id/unarchive', HttpController.unArchiveAllDocs -app.post '/project/:project_id/destroy', HttpController.destroyAllDocs +app.post('/project/:project_id/archive', HttpController.archiveAllDocs); +app.post('/project/:project_id/unarchive', HttpController.unArchiveAllDocs); +app.post('/project/:project_id/destroy', HttpController.destroyAllDocs); -app.get "/health_check", HttpController.healthCheck +app.get("/health_check", HttpController.healthCheck); -app.get '/status', (req, res)-> - res.send('docstore is alive') +app.get('/status', (req, res) => res.send('docstore is alive')); -app.use (error, req, res, next) -> - logger.error err: error, req:req, "request errored" - if error instanceof Errors.NotFoundError - res.send 404 - else - res.send(500, "Oops, something went wrong") +app.use(function(error, req, res, next) { + logger.error({err: error, req}, "request errored"); + if (error instanceof Errors.NotFoundError) { + return res.send(404); + } else { + return res.send(500, "Oops, something went wrong"); + } +}); -port = Settings.internal.docstore.port -host = Settings.internal.docstore.host +const { + port +} = Settings.internal.docstore; +const { + host +} = Settings.internal.docstore; -if !module.parent # Called directly - app.listen port, host, (error) -> - throw error if error? - logger.info "Docstore starting up, listening on #{host}:#{port}" +if (!module.parent) { // Called directly + app.listen(port, host, function(error) { + if (error != null) { throw error; } + return logger.info(`Docstore starting up, listening on ${host}:${port}`); + }); +} -module.exports = app +module.exports = app; diff --git a/services/docstore/config/settings.defaults.js b/services/docstore/config/settings.defaults.js index e45570d3fe..849fea56a1 100644 --- a/services/docstore/config/settings.defaults.js +++ b/services/docstore/config/settings.defaults.js @@ -1,31 +1,44 @@ -http = require('http') -http.globalAgent.maxSockets = 300 +/* + * decaffeinate suggestions: + * DS207: Consider shorter variations of null checks + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +const http = require('http'); +http.globalAgent.maxSockets = 300; -Settings = - internal: - docstore: - port: 3016 - host: process.env['LISTEN_ADDRESS'] or "localhost" +const Settings = { + internal: { + docstore: { + port: 3016, + host: process.env['LISTEN_ADDRESS'] || "localhost" + } + }, - mongo:{} + mongo:{}, - docstore: - healthCheck: + docstore: { + healthCheck: { project_id: process.env['HEALTH_CHECK_PROJECT_ID'] + } + }, - max_doc_length: 2 * 1024 * 1024 # 2mb + max_doc_length: 2 * 1024 * 1024 // 2mb +}; -if process.env['MONGO_CONNECTION_STRING']? - Settings.mongo.url = process.env['MONGO_CONNECTION_STRING'] -else if process.env['MONGO_HOST']? - Settings.mongo.url = "mongodb://#{process.env['MONGO_HOST']}/sharelatex" -else - Settings.mongo.url = "mongodb://127.0.0.1/sharelatex" +if (process.env['MONGO_CONNECTION_STRING'] != null) { + Settings.mongo.url = process.env['MONGO_CONNECTION_STRING']; +} else if (process.env['MONGO_HOST'] != null) { + Settings.mongo.url = `mongodb://${process.env['MONGO_HOST']}/sharelatex`; +} else { + Settings.mongo.url = "mongodb://127.0.0.1/sharelatex"; +} -if process.env['AWS_ACCESS_KEY_ID']? and process.env['AWS_SECRET_ACCESS_KEY']? and process.env['AWS_BUCKET']? - Settings.docstore.s3 = - key: process.env['AWS_ACCESS_KEY_ID'] - secret: process.env['AWS_SECRET_ACCESS_KEY'] +if ((process.env['AWS_ACCESS_KEY_ID'] != null) && (process.env['AWS_SECRET_ACCESS_KEY'] != null) && (process.env['AWS_BUCKET'] != null)) { + Settings.docstore.s3 = { + key: process.env['AWS_ACCESS_KEY_ID'], + secret: process.env['AWS_SECRET_ACCESS_KEY'], bucket: process.env['AWS_BUCKET'] + }; +} -module.exports = Settings +module.exports = Settings; From 5bca0c9bab3a9f5bdb16e19bc68ef58de70b55e9 Mon Sep 17 00:00:00 2001 From: Simon Detheridge <s@sd.ai> Date: Sun, 16 Feb 2020 14:03:45 +0000 Subject: [PATCH 21/27] prettier: convert individual decaffeinated files to Prettier format --- services/docstore/app.js | 118 +++++++++--------- services/docstore/config/settings.defaults.js | 60 ++++----- 2 files changed, 92 insertions(+), 86 deletions(-) diff --git a/services/docstore/app.js b/services/docstore/app.js index 2a14168054..725f1265c9 100644 --- a/services/docstore/app.js +++ b/services/docstore/app.js @@ -4,83 +4,85 @@ * DS207: Consider shorter variations of null checks * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const Metrics = require("metrics-sharelatex"); -Metrics.initialize("docstore"); -const Settings = require("settings-sharelatex"); -const logger = require("logger-sharelatex"); -const express = require("express"); -const bodyParser = require("body-parser"); -const Errors = require("./app/js/Errors"); -const HttpController = require("./app/js/HttpController"); -const Path = require("path"); +const Metrics = require('metrics-sharelatex') +Metrics.initialize('docstore') +const Settings = require('settings-sharelatex') +const logger = require('logger-sharelatex') +const express = require('express') +const bodyParser = require('body-parser') +const Errors = require('./app/js/Errors') +const HttpController = require('./app/js/HttpController') +const Path = require('path') - -logger.initialize("docstore"); +logger.initialize('docstore') if (Metrics.event_loop != null) { - Metrics.event_loop.monitor(logger); + Metrics.event_loop.monitor(logger) } -const app = express(); +const app = express() -app.use(Metrics.http.monitor(logger)); +app.use(Metrics.http.monitor(logger)) -Metrics.injectMetricsRoute(app); +Metrics.injectMetricsRoute(app) app.param('project_id', function(req, res, next, project_id) { - if ((project_id != null ? project_id.match(/^[0-9a-f]{24}$/) : undefined)) { - return next(); - } else { - return next(new Error("invalid project id")); - } -}); + if (project_id != null ? project_id.match(/^[0-9a-f]{24}$/) : undefined) { + return next() + } else { + return next(new Error('invalid project id')) + } +}) app.param('doc_id', function(req, res, next, doc_id) { - if ((doc_id != null ? doc_id.match(/^[0-9a-f]{24}$/) : undefined)) { - return next(); - } else { - return next(new Error("invalid doc id")); - } -}); + if (doc_id != null ? doc_id.match(/^[0-9a-f]{24}$/) : undefined) { + return next() + } else { + return next(new Error('invalid doc id')) + } +}) -Metrics.injectMetricsRoute(app); +Metrics.injectMetricsRoute(app) -app.get('/project/:project_id/doc', HttpController.getAllDocs); -app.get('/project/:project_id/ranges', HttpController.getAllRanges); -app.get('/project/:project_id/doc/:doc_id', HttpController.getDoc); -app.get('/project/:project_id/doc/:doc_id/raw', HttpController.getRawDoc); +app.get('/project/:project_id/doc', HttpController.getAllDocs) +app.get('/project/:project_id/ranges', HttpController.getAllRanges) +app.get('/project/:project_id/doc/:doc_id', HttpController.getDoc) +app.get('/project/:project_id/doc/:doc_id/raw', HttpController.getRawDoc) // Add 64kb overhead for the JSON encoding, and double the size to allow for ranges in the json payload -app.post('/project/:project_id/doc/:doc_id', bodyParser.json({limit: (Settings.max_doc_length + (64 * 1024)) * 2}), HttpController.updateDoc); -app.del('/project/:project_id/doc/:doc_id', HttpController.deleteDoc); +app.post( + '/project/:project_id/doc/:doc_id', + bodyParser.json({ limit: (Settings.max_doc_length + 64 * 1024) * 2 }), + HttpController.updateDoc +) +app.del('/project/:project_id/doc/:doc_id', HttpController.deleteDoc) -app.post('/project/:project_id/archive', HttpController.archiveAllDocs); -app.post('/project/:project_id/unarchive', HttpController.unArchiveAllDocs); -app.post('/project/:project_id/destroy', HttpController.destroyAllDocs); +app.post('/project/:project_id/archive', HttpController.archiveAllDocs) +app.post('/project/:project_id/unarchive', HttpController.unArchiveAllDocs) +app.post('/project/:project_id/destroy', HttpController.destroyAllDocs) -app.get("/health_check", HttpController.healthCheck); +app.get('/health_check', HttpController.healthCheck) -app.get('/status', (req, res) => res.send('docstore is alive')); +app.get('/status', (req, res) => res.send('docstore is alive')) app.use(function(error, req, res, next) { - logger.error({err: error, req}, "request errored"); - if (error instanceof Errors.NotFoundError) { - return res.send(404); - } else { - return res.send(500, "Oops, something went wrong"); - } -}); + logger.error({ err: error, req }, 'request errored') + if (error instanceof Errors.NotFoundError) { + return res.send(404) + } else { + return res.send(500, 'Oops, something went wrong') + } +}) -const { - port -} = Settings.internal.docstore; -const { - host -} = Settings.internal.docstore; +const { port } = Settings.internal.docstore +const { host } = Settings.internal.docstore -if (!module.parent) { // Called directly - app.listen(port, host, function(error) { - if (error != null) { throw error; } - return logger.info(`Docstore starting up, listening on ${host}:${port}`); - }); +if (!module.parent) { + // Called directly + app.listen(port, host, function(error) { + if (error != null) { + throw error + } + return logger.info(`Docstore starting up, listening on ${host}:${port}`) + }) } -module.exports = app; +module.exports = app diff --git a/services/docstore/config/settings.defaults.js b/services/docstore/config/settings.defaults.js index 849fea56a1..92bf08e324 100644 --- a/services/docstore/config/settings.defaults.js +++ b/services/docstore/config/settings.defaults.js @@ -3,42 +3,46 @@ * DS207: Consider shorter variations of null checks * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const http = require('http'); -http.globalAgent.maxSockets = 300; +const http = require('http') +http.globalAgent.maxSockets = 300 const Settings = { - internal: { - docstore: { - port: 3016, - host: process.env['LISTEN_ADDRESS'] || "localhost" - } - }, + internal: { + docstore: { + port: 3016, + host: process.env.LISTEN_ADDRESS || 'localhost' + } + }, - mongo:{}, + mongo: {}, - docstore: { - healthCheck: { - project_id: process.env['HEALTH_CHECK_PROJECT_ID'] - } - }, + docstore: { + healthCheck: { + project_id: process.env.HEALTH_CHECK_PROJECT_ID + } + }, - max_doc_length: 2 * 1024 * 1024 // 2mb -}; + max_doc_length: 2 * 1024 * 1024 // 2mb +} -if (process.env['MONGO_CONNECTION_STRING'] != null) { - Settings.mongo.url = process.env['MONGO_CONNECTION_STRING']; -} else if (process.env['MONGO_HOST'] != null) { - Settings.mongo.url = `mongodb://${process.env['MONGO_HOST']}/sharelatex`; +if (process.env.MONGO_CONNECTION_STRING != null) { + Settings.mongo.url = process.env.MONGO_CONNECTION_STRING +} else if (process.env.MONGO_HOST != null) { + Settings.mongo.url = `mongodb://${process.env.MONGO_HOST}/sharelatex` } else { - Settings.mongo.url = "mongodb://127.0.0.1/sharelatex"; + Settings.mongo.url = 'mongodb://127.0.0.1/sharelatex' } -if ((process.env['AWS_ACCESS_KEY_ID'] != null) && (process.env['AWS_SECRET_ACCESS_KEY'] != null) && (process.env['AWS_BUCKET'] != null)) { - Settings.docstore.s3 = { - key: process.env['AWS_ACCESS_KEY_ID'], - secret: process.env['AWS_SECRET_ACCESS_KEY'], - bucket: process.env['AWS_BUCKET'] - }; +if ( + process.env.AWS_ACCESS_KEY_ID != null && + process.env.AWS_SECRET_ACCESS_KEY != null && + process.env.AWS_BUCKET != null +) { + Settings.docstore.s3 = { + key: process.env.AWS_ACCESS_KEY_ID, + secret: process.env.AWS_SECRET_ACCESS_KEY, + bucket: process.env.AWS_BUCKET + } } -module.exports = Settings; +module.exports = Settings From 5fc8c3a3c763220a0598bfa45278dcb2dcb28a08 Mon Sep 17 00:00:00 2001 From: Simon Detheridge <s@sd.ai> Date: Sun, 16 Feb 2020 14:04:05 +0000 Subject: [PATCH 22/27] Uninstall coffee-script --- services/docstore/package-lock.json | 5 ----- services/docstore/package.json | 1 - 2 files changed, 6 deletions(-) diff --git a/services/docstore/package-lock.json b/services/docstore/package-lock.json index 3ed5f34f56..943dc3f164 100644 --- a/services/docstore/package-lock.json +++ b/services/docstore/package-lock.json @@ -978,11 +978,6 @@ } } }, - "coffee-script": { - "version": "1.12.7", - "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", - "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==" - }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", diff --git a/services/docstore/package.json b/services/docstore/package.json index 5181dbbc65..a0b8b1e842 100644 --- a/services/docstore/package.json +++ b/services/docstore/package.json @@ -21,7 +21,6 @@ "dependencies": { "async": "~0.8.0", "body-parser": "~1.0.2", - "coffee-script": "^1.12.7", "express": "~4.1.1", "logger-sharelatex": "^1.7.0", "metrics-sharelatex": "^2.2.0", From 10a3eadde92e22cc278c1d72c4f6442a50d7814c Mon Sep 17 00:00:00 2001 From: Simon Detheridge <s@sd.ai> Date: Sun, 16 Feb 2020 14:06:01 +0000 Subject: [PATCH 23/27] Upgrade sha1 hashes to sha512 --- services/docstore/package-lock.json | 502 ++++++++++++++-------------- 1 file changed, 252 insertions(+), 250 deletions(-) diff --git a/services/docstore/package-lock.json b/services/docstore/package-lock.json index 943dc3f164..fc2241cbd3 100644 --- a/services/docstore/package-lock.json +++ b/services/docstore/package-lock.json @@ -28,7 +28,7 @@ "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "dev": true } } @@ -244,7 +244,7 @@ "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==" }, "gcp-metadata": { "version": "0.9.3", @@ -324,7 +324,7 @@ "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" }, "semver": { "version": "6.1.1", @@ -341,7 +341,7 @@ "@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" }, "@protobufjs/base64": { "version": "1.1.2", @@ -356,12 +356,12 @@ "@protobufjs/eventemitter": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" }, "@protobufjs/fetch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", "requires": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" @@ -370,27 +370,27 @@ "@protobufjs/float": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" }, "@protobufjs/inquire": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" }, "@protobufjs/path": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" }, "@protobufjs/pool": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" }, "@protobufjs/utf8": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, "@sindresorhus/is": { "version": "0.15.0", @@ -531,7 +531,7 @@ "accepts": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.0.1.tgz", - "integrity": "sha1-weBtYT5iRrqHRnjW2bkjibfOMQw=", + "integrity": "sha512-EsBDjbbGp44Tq6UGW6YE4cgD2xF1MIIyK7Vn+sElHW3EiSgqoIetsTiwFytb9YxODl6YVc4IIY28zeQ0JKGCLQ==", "requires": { "mime": "~1.2.11", "negotiator": "~0.4.0" @@ -603,7 +603,7 @@ "aria-query": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz", - "integrity": "sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=", + "integrity": "sha512-majUxHgLehQTeSA+hClx+DY09OVUqG3GtezWkF1krgLGNdlDu9l9V8DaqNMWbq4Eddc8wsyDA0hpDUtnYxQEXw==", "dev": true, "requires": { "ast-types-flow": "0.0.7", @@ -639,27 +639,27 @@ "asn1": { "version": "0.1.11", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", - "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=", + "integrity": "sha512-Fh9zh3G2mZ8qM/kwsiKwL2U2FmXxVsboP4x1mXjnhKHv3SmzaBZoYvxEQJz/YS2gnCgd8xlAVWcZnQyC9qZBsA==", "dev": true, "optional": true }, "assert-plus": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", - "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=", + "integrity": "sha512-brU24g7ryhRwGCI2y+1dGQmQXiZF7TtIj583S96y0jjdajIe6wn8BuXyELYhvD22dtIxDQVFk04YTJwwdwOYJw==", "dev": true, "optional": true }, "assertion-error": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.0.tgz", - "integrity": "sha1-x/hUOP3UZrx8oWq5DIFRN5el0js=", + "integrity": "sha512-g/gZV+G476cnmtYI+Ko9d5khxSoCSoom/EaNmmCfwpOvBXEJ18qwFrxfP1/CsIqk2no1sAKKwxndV0tP7ROOFQ==", "dev": true }, "ast-types-flow": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", + "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", "dev": true }, "astral-regex": { @@ -671,7 +671,7 @@ "async": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/async/-/async-0.8.0.tgz", - "integrity": "sha1-7mXsdymML/FFa8RBigUtDwZDURI=" + "integrity": "sha512-M2LC+aqW7VetFcnFiYEbjUsmASW6GSsMNkRzhUzwHoQNfNIRClf5GLgozwuJ4tAMLAfjywrKyQ2wWiODJivQmg==" }, "async-listener": { "version": "0.6.10", @@ -685,12 +685,12 @@ "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "aws-sign2": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", - "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=", + "integrity": "sha512-oqUX0DM5j7aPWPCnpWebiyNIj2wiNI87ZxnOMoGv0aE4TGlBy2N+5iWc6dQ/NOKZaBD2W6PVz8jtOGkWzSC5EA==", "dev": true, "optional": true }, @@ -742,7 +742,7 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "integrity": "sha512-9Y0g0Q8rmSt+H33DfKv7FOc3v+iRI+o1lbzt8jGcIosYW37IIW/2XVYq5NPdmaD5NQ59Nk26Kl/vZbwW9Fr8vg==" }, "base64-js": { "version": "1.3.0", @@ -752,7 +752,7 @@ "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", "requires": { "tweetnacl": "^0.14.3" } @@ -773,12 +773,12 @@ "bintrees": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.1.tgz", - "integrity": "sha1-DmVcm5wkNeqraL9AJyJtK1WjRSQ=" + "integrity": "sha512-tbaUB1QpTIj4cKY8c1rvNAvEQXA+ekzHmbe4jzNfW3QWsF9GnnP/BRWyl6/qqS53heoYJ93naaFcm/jooONH8g==" }, "body-parser": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.0.2.tgz", - "integrity": "sha1-NGFHmjJ4/gD8rr7DMUu1T8T3tHw=", + "integrity": "sha512-/VlRWmVVwfh8rYG/MHGIwesdJYdxBgeddggFG5ssLfX/Qhwt4NKEQhvzwdzVRcy2RhLxni1MKe0uuPfP/unjyw==", "requires": { "qs": "~0.6.6", "raw-body": "~1.1.2", @@ -788,14 +788,15 @@ "boolify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/boolify/-/boolify-1.0.1.tgz", - "integrity": "sha1-tcCeF8rNET0Rt7s+04TMASmU2Gs=", + "integrity": "sha512-ma2q0Tc760dW54CdOyJjhrg/a54317o1zYADQJFgperNGKIKgAUGIcKnuMiff8z57+yGlrGNEt4lPgZfCgTJgA==", "dev": true }, "boom": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", - "integrity": "sha1-emNune1O/O+xnO9JR6PGffrukRs=", + "integrity": "sha512-OvfN8y1oAxxphzkl2SnCS+ztV/uVKTATtgLjWYg/7KwcNyf3rzpHxNQJZCKtsZd4+MteKczhWbSjtEX4bGgU9g==", "dev": true, + "optional": true, "requires": { "hoek": "0.9.x" } @@ -812,7 +813,7 @@ "browser-stdout": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "integrity": "sha512-7Rfk377tpSM9TWBEeHs0FlDZGoAIei2V/4MdZJoFMBFAK6BqLpxAIUepGRHGdPFgGsLb02PXovC4qddyHvQqTg==", "dev": true }, "bson": { @@ -823,17 +824,17 @@ "buffer-crc32": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.1.tgz", - "integrity": "sha1-vj5TgvwCttYySVasGvmKqYsIU0w=" + "integrity": "sha512-vMfBIRp/wjlpueSz7Sb0OmO7C5SH58SSmbsT8G4D48YfO/Zgbr29xNXMpZVSC14ujVJfrZZH1Bl+kXYRQPuvfQ==" }, "buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" }, "buffer-shims": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", - "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=" + "integrity": "sha512-Zy8ZXMyxIT6RMTeY7OP/bDndfj6bwCan7SS98CEndS6deHwWPpseeHlwarNcBim+etXnF9HBc1non5JgDaJU1g==" }, "builtin-modules": { "version": "3.1.0", @@ -843,7 +844,7 @@ "bunyan": { "version": "0.22.3", "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-0.22.3.tgz", - "integrity": "sha1-ehncG0yMZF90AkGnQPIkUUfGfsI=", + "integrity": "sha512-v9dd5qmd6nJHEi7fiNo1fR2pMpE8AiB47Ap984p4iJKj+dEA69jSccmq6grFQn6pxIh0evvKpC5XO1SKfiaRoQ==", "dev": true, "requires": { "dtrace-provider": "0.2.8", @@ -853,7 +854,7 @@ "bytes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", - "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=" + "integrity": "sha512-/x68VkHLeTl3/Ll8IvxdwzhrT+IyKc52e/oyHhA2RwqPqswSnjVbSddfPRwAsJtbilMAPSRWwAlpxdYsSWOTKQ==" }, "callsites": { "version": "3.1.0", @@ -881,12 +882,12 @@ "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" }, "chai": { "version": "1.9.2", "resolved": "https://registry.npmjs.org/chai/-/chai-1.9.2.tgz", - "integrity": "sha1-Pxog+CsLnXQ3V30k1vErGmnTtZA=", + "integrity": "sha512-olRoaitftnzWHFEAza6MXR4w+FfZrOVyV7r7U/Z8ObJefCgL8IuWkAuASJjSXrpP9wvgoL8+1dB9RbMLc2FkNg==", "dev": true, "requires": { "assertion-error": "1.0.0", @@ -907,7 +908,7 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true }, "supports-color": { @@ -939,7 +940,7 @@ "cli-width": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "integrity": "sha512-EJLbKSuvHTrVRynOXCYFTbQKZOFXWNe3/6DN1yrEH3TuuZT1x4dMQnCHnfCrBUUiGjO63enEIfaB17VaRl2d4A==", "dev": true }, "cliui": { @@ -962,7 +963,7 @@ "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", "dev": true }, "string-width": { @@ -990,13 +991,13 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, "combined-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", - "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", + "integrity": "sha512-qfexlmLp9MyrkajQVyjEDb0Vj+KhRgR/rxLiVhaihlT+ZkX0lReqtH6Ack40CvMDERR4b5eFp3CreskpBs1Pig==", "dev": true, "optional": true, "requires": { @@ -1018,7 +1019,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "console-log-level": { "version": "1.4.1", @@ -1028,7 +1029,7 @@ "contains-path": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "integrity": "sha512-OKZnPGeMQy2RPaUIBPFFd71iNf4791H12MCRuVQDnzGRwCYNYmTDy5pdafo2SLAcEMKzTOQnLWG4QdcjeJUMEg==", "dev": true }, "continuation-local-storage": { @@ -1043,12 +1044,12 @@ "cookie": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.2.tgz", - "integrity": "sha1-cv7D0k5Io0Mgc9kMEmQgBQYQBLE=" + "integrity": "sha512-+mHmWbhevLwkiBf7QcbZXHr0v4ZQQ/OgHk3fsQHrsMMiGzuvAmU/YMUR+ZfrO/BLAGIWFfx2Z7Oyso0tZR/wiA==" }, "cookie-signature": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.3.tgz", - "integrity": "sha1-kc2ZfMUftkFZVzjGnNoCAyj1D/k=" + "integrity": "sha512-/KzKzsm0OlguYov01OlOpTkX5MhBKUmfL/KMum7R80rPKheb9AwUzr78TwtBt1OdbnWrt4X+wxbTfcQ3noZqHw==" }, "core-js": { "version": "3.6.4", @@ -1059,7 +1060,7 @@ "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" }, "cross-spawn": { "version": "6.0.5", @@ -1077,7 +1078,7 @@ "cryptiles": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", - "integrity": "sha1-7ZH/HxetE9N0gohZT4pIoNJvMlw=", + "integrity": "sha512-gvWSbgqP+569DdslUiCelxIv3IYK5Lgmq1UrRnk+s1WxQOQ16j3GPDcjdtgL5Au65DU/xQi6q3xPtf5Kta+3IQ==", "dev": true, "optional": true, "requires": { @@ -1087,7 +1088,7 @@ "ctype": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", - "integrity": "sha1-gsGMJGH3QRTvFsE1IkrQuRRMoS8=", + "integrity": "sha512-T6CEkoSV4q50zW3TlTHMbzy1E5+zlnNcY+yb7tWVYlTwPhx9LpnfAkd4wecpWknDyptp4k97LUZeInlf6jdzBg==", "dev": true, "optional": true }, @@ -1100,7 +1101,7 @@ "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", "requires": { "assert-plus": "^1.0.0" }, @@ -1108,25 +1109,25 @@ "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==" } } }, "debug": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/debug/-/debug-0.8.1.tgz", - "integrity": "sha1-IP9NJvXkIstoobrLu2EDmtjBwTA=" + "integrity": "sha512-HlXEJm99YsRjLJ8xmuz0Lq8YUwrv7hAJkTEr6/Em3sUlSUNl0UdFA+1SrY4fnykeq1FVkUEUtwRGHs9VvlYbGA==" }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true }, "deep-eql": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", - "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", + "integrity": "sha512-6sEotTRGBFiNcqVoeHwnfopbSpi5NbH1VWJmYCVkmxMmaVTT0bUTrNaGyBwhgP4MZL012W/mkzIn3Da+iDYweg==", "dev": true, "requires": { "type-detect": "0.1.1" @@ -1135,7 +1136,7 @@ "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=", + "integrity": "sha512-GtxAN4HvBachZzm4OnWqc45ESpUCMwkYcsjnsPs23FwJbsO+k4t0k9bQCgOmzIlpHO28+WPK/KRbRk0DDHuuDw==", "dev": true }, "define-properties": { @@ -1155,7 +1156,7 @@ "delayed-stream": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", - "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", + "integrity": "sha512-v+7uBd1pqe5YtgPacIIbZ8HuHeLFVNe4mUEyFDXL6KiqzEykjbw+5mXZXpGFgNVasdL4jWKgaKIXrEHiynN1LA==", "dev": true, "optional": true }, @@ -1177,7 +1178,7 @@ "dtrace-provider": { "version": "0.2.8", "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.2.8.tgz", - "integrity": "sha1-4kPxkhmqlfvw2PL/sH9b1k6U/iA=", + "integrity": "sha512-wufYnYt4ISHnT9MEiRgQ3trXuolt7mICTa/ckT+KYHR667K9H82lmI8KM7zKUJ8l5I343A34wJnvL++1TJn1iA==", "dev": true, "optional": true }, @@ -1195,12 +1196,12 @@ "each-series": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/each-series/-/each-series-1.0.0.tgz", - "integrity": "sha1-+Ibmxm39sl7x/nNWQUbuXLR4r8s=" + "integrity": "sha512-4MQloCGGCmT5GJZK5ibgJSvTK1c1QSrNlDvLk6fEyRxjZnXjl+NNFfzhfXpmnWh33Owc9D9klrdzCUi7yc9r4Q==" }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", "requires": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" @@ -1239,7 +1240,7 @@ "ent": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", - "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=" + "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==" }, "error-ex": { "version": "1.3.2", @@ -1283,12 +1284,12 @@ "es6-promise": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz", - "integrity": "sha1-7FYjOGgDKQkgcXDDlEjiREndH8Q=" + "integrity": "sha512-oj4jOSXvWglTsc3wrw86iom3LDPOx1nbipQk+jaG3dy+sMRM6ReSgVr/VlmBuF6lXUrflN9DCcQHeSbAwGUl4g==" }, "es6-promisify": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==", "requires": { "es6-promise": "^4.0.3" }, @@ -1303,12 +1304,12 @@ "escape-html": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz", - "integrity": "sha1-GBoobq05ejmpKFfPsdQwUuNWv/A=" + "integrity": "sha512-z6kAnok8fqVTra7Yu77dZF2Y6ETJlxH58wN38wNyuNQLm8xXdKnfNrlSmfXsTePWP03rRVUKHubtUwanwUi7+g==" }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true }, "eslint": { @@ -1531,7 +1532,7 @@ "doctrine": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "integrity": "sha512-lsGyRuYr4/PIB0txi+Fy2xOMI2dGaTguCaotzFGkVZuKR5usKfcRWIFKNM3QNrU7hh/+w2bwTW+ZeXPK5l8uVg==", "dev": true, "requires": { "esutils": "^2.0.2", @@ -1767,7 +1768,7 @@ "express": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/express/-/express-4.1.2.tgz", - "integrity": "sha1-yx0RQlVximWhvNaVgDbvcgxSlIc=", + "integrity": "sha512-U7G/TwoXu9uSHtGnvW6WQyLz3rP+qp3sHUiNpKw5Mz2o6DGenpxngH5tGnxgg09Hjqzje2CzZKukPoZfemepYQ==", "requires": { "accepts": "1.0.1", "buffer-crc32": "0.2.1", @@ -1807,12 +1808,12 @@ "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==" }, "fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==" }, "fast-diff": { "version": "1.2.0", @@ -1823,12 +1824,12 @@ "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + "integrity": "sha512-eIgZvM9C3P05kg0qxfqaVU6Tma4QedCPIByQOcemV0vju8ot3cS2DpHi4m2G2JvbSMI152rjfLX0p1pkSdyPlQ==" }, "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, "fast-text-encoding": { @@ -1862,7 +1863,7 @@ "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", "dev": true, "requires": { "locate-path": "^2.0.0" @@ -1871,7 +1872,7 @@ "findit2": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/findit2/-/findit2-2.2.3.tgz", - "integrity": "sha1-WKRmaX34piBc39vzlVNri9d3pfY=" + "integrity": "sha512-lg/Moejf4qXovVutL0Lz4IsaPoNYMuxt4PA0nGqFxnJ1CTTGGlEO2wKgoDpwknhvZ8k4Q2F+eesgkLbG2Mxfog==" }, "flat-cache": { "version": "2.0.1", @@ -1936,13 +1937,13 @@ "forever-agent": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", - "integrity": "sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA=", + "integrity": "sha512-PDG5Ef0Dob/JsZUxUltJOhm/Y9mlteAE+46y3M9RBz/Rd3QVENJ75aGRhN56yekTUboaBIkd8KVWX2NjF6+91A==", "dev": true }, "form-data": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", - "integrity": "sha1-kavXiKupcCsaq/qLwBAxoqyeOxI=", + "integrity": "sha512-x8eE+nzFtAMA0YYlSxf/Qhq6vP1f8wSoZ7Aw1GuctBcmudCNuTUmmx45TfEplyb6cjsZO/jvh6+1VpZn24ez+w==", "dev": true, "optional": true, "requires": { @@ -1954,7 +1955,7 @@ "async": { "version": "0.9.2", "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "integrity": "sha512-l6ToIJIotphWahxxHyzK9bnLR6kM4jJIIgLShZeqLY7iboHoGkdgFl7W2/Ivi4SkMJYGKqW8vSuk0uKUj6qsSw==", "dev": true, "optional": true } @@ -1963,7 +1964,7 @@ "formatio": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz", - "integrity": "sha1-87IWfZBoxGmKjVH092CjmlTYGOs=", + "integrity": "sha512-YAF05v8+XCxAyHOdiiAmHdgCVPrWO8X744fYIPtBciIorh5LndWfi1gjeJ16sTbJhzek9kd+j3YByhohtz5Wmg==", "dev": true, "requires": { "samsam": "1.x" @@ -1972,12 +1973,12 @@ "fresh": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.2.2.tgz", - "integrity": "sha1-lzHc9WeMf660T7kDxPct9VGH+nc=" + "integrity": "sha512-ZGGi8GROK//ijm2gB33sUuN9TjN1tC/dvG4Bt4j6IWrVGpMmudUBCxx+Ir7qePsdREfkpQC4FL8W0jeSOsgv1w==" }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, "function-bind": { @@ -1989,7 +1990,7 @@ "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", "dev": true }, "gaxios": { @@ -2027,7 +2028,7 @@ "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", "requires": { "assert-plus": "^1.0.0" }, @@ -2035,14 +2036,14 @@ "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==" } } }, "glob": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", - "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "integrity": "sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==", "optional": true, "requires": { "inflight": "^1.0.4", @@ -2120,7 +2121,7 @@ "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==" }, "har-validator": { "version": "5.1.3", @@ -2143,7 +2144,7 @@ "has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", "dev": true, "requires": { "ansi-regex": "^2.0.0" @@ -2152,7 +2153,7 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", "dev": true } } @@ -2160,7 +2161,7 @@ "has-flag": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "integrity": "sha512-P+1n3MnwjR/Epg9BBo1KT8qbye2g2Ou4sFumihwt6I4tsUX7jnLcX4BTOSKg/B1ZrIYMN9FcEnG4x5a7NB8Eng==", "dev": true }, "has-symbols": { @@ -2172,7 +2173,7 @@ "hawk": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.0.0.tgz", - "integrity": "sha1-uQuxaYByhUEdp//LjdJZhQLTtS0=", + "integrity": "sha512-Sg+VzrI7TjUomO0rjD6UXawsj50ykn5sB/xKNW/IenxzRVyw/wt9A2FLzYpGL/r0QG5hyXY8nLx/2m8UutoDcg==", "dev": true, "optional": true, "requires": { @@ -2185,7 +2186,7 @@ "he": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "integrity": "sha512-z/GDPjlRMNOa2XJiB4em8wJpuuBfrFOlYKTZxtpkdr1uPdibHI8rYA3MY0KDObpVyaes0e/aunid/t88ZI2EKA==", "dev": true }, "hex2dec": { @@ -2196,8 +2197,9 @@ "hoek": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", - "integrity": "sha1-PTIkYrrfB3Fup+uFuviAec3c5QU=", - "dev": true + "integrity": "sha512-ZZ6eGyzGjyMTmpSPYVECXy9uNfqBR7x5CavhUaLOeD6W0vWK1mp/b7O3f86XE0Mtfo9rZ6Bh3fnuw9Xr8MF9zA==", + "dev": true, + "optional": true }, "hosted-git-info": { "version": "2.8.5", @@ -2208,7 +2210,7 @@ "http-signature": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", - "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", + "integrity": "sha512-coK8uR5rq2IMj+Hen+sKPA5ldgbCc1/spPdKCL1Fw6h+D0s/2LzMcRK0Cqufs1h0ryx/niwBHGFu8HC3hwU+lA==", "dev": true, "optional": true, "requires": { @@ -2277,7 +2279,7 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true }, "indent-string": { @@ -2289,7 +2291,7 @@ "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "requires": { "once": "^1.3.0", "wrappy": "1" @@ -2298,7 +2300,7 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" }, "inquirer": { "version": "7.0.4", @@ -2340,7 +2342,7 @@ "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true }, "is-buffer": { @@ -2363,7 +2365,7 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true }, "is-fullwidth-code-point": { @@ -2384,7 +2386,7 @@ "is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "integrity": "sha512-NECAi6wp6CgMesHuVUEK8JwjCvm/tvnn5pCbB42JOHp3mgUizN0nagXu4HEqQZBkieGEQ+jVcMKWqoVd6CDbLQ==", "dev": true }, "is-regex": { @@ -2414,23 +2416,23 @@ "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" }, "js-tokens": { "version": "4.0.0", @@ -2451,7 +2453,7 @@ "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" }, "jsesc": { "version": "2.5.2", @@ -2462,7 +2464,7 @@ "json-bigint": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-0.3.0.tgz", - "integrity": "sha1-DM2RLEuCcNBfBW+9E4FLU9OCWx4=", + "integrity": "sha512-u+c/u/F+JNPUekHCFyGVycRPyh9UHD5iUhSyIAn10kxbDTJxijwAbT6XHaONEOXuGGfmWUSroheXgHcml4gLgg==", "requires": { "bignumber.js": "^7.0.0" } @@ -2470,7 +2472,7 @@ "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + "integrity": "sha512-a3xHnILGMtk+hDOqNwHzF6e2fNbiMrXZvxKQiEv2MlgQP+pjIOzqAmKYD2mDpXYE/44M7g+n9p2bKkYWDUcXCQ==" }, "json-schema-traverse": { "version": "0.4.1", @@ -2480,18 +2482,18 @@ "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "integrity": "sha512-4Dj8Rf+fQ+/Pn7C5qeEX02op1WfOss3PKTE9Nsop3Dx+6UPxlm1dr/og7o2cRa5hNN07CACr4NFzRLtj/rjWog==", "requires": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", @@ -2502,7 +2504,7 @@ "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==" } } }, @@ -2544,7 +2546,7 @@ "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", "dev": true, "requires": { "prelude-ls": "~1.1.2", @@ -2554,7 +2556,7 @@ "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "integrity": "sha512-3p6ZOGNbiX4CdvEd1VcE6yi78UrGNpjHO33noGwHCnT/o2fyllJDepsm8+mFFv/DvtwFHht5HIHSyOy5a+ChVQ==", "dev": true, "requires": { "graceful-fs": "^4.1.2", @@ -2566,7 +2568,7 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "dev": true } } @@ -2574,7 +2576,7 @@ "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", "dev": true, "requires": { "p-locate": "^2.0.0", @@ -2590,7 +2592,7 @@ "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", "dev": true }, "lodash.merge": { @@ -2602,12 +2604,12 @@ "lodash.pickby": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.pickby/-/lodash.pickby-4.6.0.tgz", - "integrity": "sha1-feoh2MGNdwOifHBMFdO4SmfjOv8=" + "integrity": "sha512-AZV+GsS/6ckvPOVQPXSiFFacKvKB4kOQu6ynt9wz0F3LO4R9Ij4K1ddYsIytDpSgLz88JHd9P+oaLeej5/Sl7Q==" }, "lodash.unescape": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz", - "integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=", + "integrity": "sha512-DhhGRshNS1aX6s5YdBE3njCCouPgnG29ebyHvImlZzXZf2SHgt+J08DHgytTPnpywNbO1Y8mNUFyQuIDBq2JZg==", "dev": true }, "logger-sharelatex": { @@ -2623,17 +2625,17 @@ "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==" }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==" }, "bunyan": { "version": "1.8.12", "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.12.tgz", - "integrity": "sha1-8VDw9nSKvdcq6uhPBEA74u8RN5c=", + "integrity": "sha512-dmDUbGHeGcvCDLRFOscZkwx1ZO/aFz3bJOCi5nCgzdhFGPxwK+y5AcDBnqagNGlJZ7lje/l6JUEz9mQcutttdg==", "requires": { "dtrace-provider": "~0.8", "moment": "^2.10.6", @@ -2652,12 +2654,12 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" }, "dtrace-provider": { "version": "0.8.7", "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.7.tgz", - "integrity": "sha1-3JObTT4GIM/gwc2APQ0tftBP/QQ=", + "integrity": "sha512-V+HIGbAdxCIxddHNDwzXi6cx8Cz5RRlQOVcsryHfsyVVebpBEnDwHSgqxpgKzqeU/6/0DWqRLAGUwkbg2ecN1Q==", "optional": true, "requires": { "nan": "^2.10.0" @@ -2666,7 +2668,7 @@ "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==" }, "form-data": { "version": "2.3.3", @@ -2681,7 +2683,7 @@ "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", "requires": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", @@ -2737,7 +2739,7 @@ "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "requires": { "safe-buffer": "^5.0.1" } @@ -2758,7 +2760,7 @@ "loglevel-colored-level-prefix": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/loglevel-colored-level-prefix/-/loglevel-colored-level-prefix-1.0.0.tgz", - "integrity": "sha1-akAhj9x64V/HbD0PPmdsRlOIYD4=", + "integrity": "sha512-u45Wcxxc+SdAlh4yeF/uKlC1SPUPCy0gullSNKXod5I4bmifzk+Q4lSLExNEVn19tGaJipbZ4V4jbFn79/6mVA==", "dev": true, "requires": { "chalk": "^1.1.3", @@ -2768,19 +2770,19 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", "dev": true }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", "dev": true }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", "dev": true, "requires": { "ansi-styles": "^2.2.1", @@ -2793,7 +2795,7 @@ "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", "dev": true, "requires": { "ansi-regex": "^2.0.0" @@ -2802,7 +2804,7 @@ "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", "dev": true } } @@ -2838,12 +2840,12 @@ "lsmod": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lsmod/-/lsmod-1.0.0.tgz", - "integrity": "sha1-mgD3bco26yP6BTUK/htYXUKZ5ks=" + "integrity": "sha512-Y+6V75r+mGWzWEPr9h6PFmStielICu5JBHLUg18jCsD2VFmEfgHbq/EgnY4inElsUD9eKL9id1qp34w46rSIKQ==" }, "lynx": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/lynx/-/lynx-0.1.1.tgz", - "integrity": "sha1-Mxjc7xaQi4KG6Bisz9sxzXQkj50=", + "integrity": "sha512-JI52N0NwK2b/Md0TFPdPtUBI46kjyJXF7+q08l2yvQ56q6QA8s7ZjZQQRoxFpS2jDXNf/B0p8ID+OIKcTsZwzw==", "requires": { "mersenne": "~0.0.3", "statsd-parser": "~0.0.4" @@ -2861,7 +2863,7 @@ "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "integrity": "sha512-7Wl+Jz+IGWuSdgsQEJ4JunV0si/iMhg42MnQQG6h1R6TNeVenp4U9x5CC5v/gYqz/fENLQITAWXidNtVL0NNbw==", "dev": true, "optional": true } @@ -2876,12 +2878,12 @@ "merge-descriptors": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-0.0.2.tgz", - "integrity": "sha1-w2pSp4FDdRPFcnXzndnTF1FKyMc=" + "integrity": "sha512-dYBT4Ep+t/qnPeJcnMymmhTdd4g8/hn48ciaDqLAkfRf8abzLPS6Rb6EBdz5CZCL8tzZuI5ps9MhGQGxk+EuKg==" }, "mersenne": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/mersenne/-/mersenne-0.0.4.tgz", - "integrity": "sha1-QB/ex+whzbngPNPTAhOY2iGycIU=" + "integrity": "sha512-XoSUL+nF8hMTKGQxUs8r3Btdsf1yuKKBdCCGbh3YXgCXuVKishpZv1CNc385w9s8t4Ynwc5h61BwW/FCVulkbg==" }, "messageformat": { "version": "2.3.0", @@ -2909,7 +2911,7 @@ "methods": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/methods/-/methods-0.1.0.tgz", - "integrity": "sha1-M11Cnu/SG3us8unJIqjSvRSjDk8=" + "integrity": "sha512-N4cn4CbDqu7Fp3AT4z3AsO19calgczhsmCGzXLCiUOrWg9sjb1B+yKFKOrnnPGKKvjyJBmw+k6b3adFN2LbuBw==" }, "metrics-sharelatex": { "version": "2.2.0", @@ -2928,14 +2930,14 @@ "coffee-script": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.6.0.tgz", - "integrity": "sha1-gIs5bhEPU9AhoZpO8fZb4OjjX6M=" + "integrity": "sha512-Tx8itEfCsQp8RbLDFt7qwjqXycAx2g6SI7//4PPUR2j6meLmNifYm6zKrNDcU1+Q/GWRhjhEZk7DaLG1TfIzGA==" } } }, "mime": { "version": "1.2.11", "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", - "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=" + "integrity": "sha512-Ysa2F/nqTNGHhhm9MV8ure4+Hc+Y8AWiqUdHxsO7xu8zc92ND9f3kpALHjaP026Ft17UfxrMt95c50PLUeynBw==" }, "mime-db": { "version": "1.40.0", @@ -2967,12 +2969,12 @@ "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "integrity": "sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q==" }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "integrity": "sha512-SknJC52obPfGQPnjIkXbmA6+5H15E+fR+E4iR2oQ3zzCLbd7/ONua69R/Gw7AgkTLsRG+r5fzksYwWe1AgTyWA==", "requires": { "minimist": "0.0.8" } @@ -3041,7 +3043,7 @@ "module-details-from-path": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", - "integrity": "sha1-EUyUlnPiqKNenTV4hSeqN7Z52is=" + "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==" }, "moment": { "version": "2.24.0", @@ -3062,7 +3064,7 @@ "readable-stream": { "version": "2.2.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", - "integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=", + "integrity": "sha512-a6ibcfWFhgihuTw/chl+u3fB5ykBZFmnvpyZHebY0MCQE4vvYcsCLpCeaQ1BkH7HdJYavNSqF0WDLeo4IPHQaQ==", "requires": { "buffer-shims": "~1.0.0", "core-util-is": "~1.0.0", @@ -3095,7 +3097,7 @@ "mongojs": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/mongojs/-/mongojs-2.4.0.tgz", - "integrity": "sha1-8of7/UV/7fWItakBHmhRPZ3TK/s=", + "integrity": "sha512-QqqJ06x5EBBG121dxXbm0kQ8mNVAOGMeG3RKbNvtbiFez5EhCTMDUikYcsa0V9tphlvsheO5riMHcXHxW0q3lw==", "requires": { "each-series": "^1.0.0", "mongodb": "^2.0.45", @@ -3110,7 +3112,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "mute-stream": { "version": "0.0.8", @@ -3121,7 +3123,7 @@ "mv": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", - "integrity": "sha1-rmzg1vbV4KT32JN5jQPB6pVZtqI=", + "integrity": "sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg==", "optional": true, "requires": { "mkdirp": "~0.5.1", @@ -3137,25 +3139,25 @@ "native-promise-only": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz", - "integrity": "sha1-IKMYwwy0X3H+et+/eyHJnBRy7xE=", + "integrity": "sha512-zkVhZUA3y8mbz652WrL5x0fB0ehrBkulWT3TomAQ9iDtyXZvzKeEA6GPxAItBYeNYl5yngKRX612qHOhvMkDeg==", "dev": true }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, "ncp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", - "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=", + "integrity": "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA==", "optional": true }, "negotiator": { "version": "0.4.9", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.9.tgz", - "integrity": "sha1-kuRrbbU8fkIe1koryU8IvnYw3z8=" + "integrity": "sha512-fvi5GQce2TGDzanaTxNY3bboxjdce18sqwNylY439wkEkiJIyTMhGFMdlPCvDsIPa9IKIfhKwCMWEQ9YpZgb1Q==" }, "nice-try": { "version": "1.0.5", @@ -3179,13 +3181,13 @@ "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", "dev": true }, "path-to-regexp": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", - "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", + "integrity": "sha512-nifX1uj4S9IrK/w3Xe7kKvNEepXivANs9ng60Iq7PU/BlouV3yL/VUhFqTuTq33ykwUqoNcTeGo5vdOBP4jS/Q==", "dev": true, "requires": { "isarray": "0.0.1" @@ -3206,7 +3208,7 @@ "node-uuid": { "version": "1.4.8", "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", - "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", + "integrity": "sha512-TkCET/3rr9mUuRp+CpO7qfgT++aAxfDRaalQhwPFzI9BY/2rCDn6OfpZOVggi1AXfTPpfkTrg5f5WQx5G1uLxA==", "dev": true }, "normalize-package-data": { @@ -3224,14 +3226,14 @@ "oauth-sign": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz", - "integrity": "sha1-y1QPk7srIqfVlBaRoojWDo6pOG4=", + "integrity": "sha512-Tr31Sh5FnK9YKm7xTUPyDMsNOvMqkVDND0zvK/Wgj7/H9q8mpye0qG2nVzrnsvLhcsX5DtqXD0la0ks6rkPCGQ==", "dev": true, "optional": true }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true }, "object-inspect": { @@ -3297,7 +3299,7 @@ "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "requires": { "wrappy": "1" } @@ -3328,7 +3330,7 @@ "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", "dev": true }, "p-limit": { @@ -3342,7 +3344,7 @@ "p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", "dev": true, "requires": { "p-limit": "^1.1.0" @@ -3360,7 +3362,7 @@ "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", "dev": true } } @@ -3382,12 +3384,12 @@ "parse-duration": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/parse-duration/-/parse-duration-0.1.1.tgz", - "integrity": "sha1-ExFN3JiRwezSgANiRFVN5DZHoiY=" + "integrity": "sha512-MPkERaX8suJ97HH2TtTN81ASYdFWouJqcnfVYSFHvWCI13vN4NzbvKsBOYN/7o8cTSoaNVMz4H8wG7GjTj0q6g==" }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==", "dev": true, "requires": { "error-ex": "^1.2.0" @@ -3396,7 +3398,7 @@ "parse-mongo-url": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/parse-mongo-url/-/parse-mongo-url-1.1.1.tgz", - "integrity": "sha1-ZiON9fjnwMjKTNlw1KtqE3PrdbU=" + "integrity": "sha512-7bZUusQIrFLwvsLHBnCz2WKYQ5LKO/LwKPnvQxbMIh9gDx8H5ZsknRmLjZdn6GVdrgVOwqDrZKsY0qDLNmRgcw==" }, "parse-ms": { "version": "2.1.0", @@ -3406,29 +3408,29 @@ "parseurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.0.1.tgz", - "integrity": "sha1-Llfc5u/dN8NRhwEDCUTCK/OIt7Q=" + "integrity": "sha512-6W9+0+9Ihayqwjgp4OaLLqZ3KDtqPY2PtUPz8YNiy4PamjJv+7x6J9GO93O9rUZOLgaanTPxsKTasxqKkO1iSw==" }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", "dev": true }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" }, "path-is-inside": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", "dev": true }, "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", "dev": true }, "path-parse": { @@ -3439,12 +3441,12 @@ "path-to-regexp": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.2.tgz", - "integrity": "sha1-mysVH5zDAYye6lDKlXKeBXgXErQ=" + "integrity": "sha512-BZU7Qr+qKkXJX9UBypMNikdZ85cQSjtfMhUykJFLJn4SNF0jhEbb9nMRpnNdA76ESryY8JpMA4k6XKdz3JS1pw==" }, "path-type": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "integrity": "sha512-dUnb5dXUf+kzhC/W/F4e5/SkluXIFf5VUHolW1Eg1irn1hGWjPGdsRcvYJ1nD6lhk8Ir7VM0bHJKsYTx8Jx9OQ==", "dev": true, "requires": { "pify": "^2.0.0" @@ -3453,7 +3455,7 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "dev": true } } @@ -3461,7 +3463,7 @@ "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" }, "pify": { "version": "4.0.1", @@ -3471,7 +3473,7 @@ "pkg-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "integrity": "sha512-ojakdnUgL5pzJYWw2AIDEupaQCX5OPbM688ZevubICjdIX01PRSYKqm33fJoCOJBRseYCTUlQRnBNX+Pchaejw==", "dev": true, "requires": { "find-up": "^2.1.0" @@ -3480,7 +3482,7 @@ "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", "dev": true }, "prettier": { @@ -3519,13 +3521,13 @@ "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "integrity": "sha512-wFUFA5bg5dviipbQQ32yOQhl6gcJaJXiHE7dvR8VYPG97+J/GNC5FKGepKdEDUFeXRzDxPF1X/Btc8L+v7oqIQ==", "dev": true }, "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", "dev": true, "requires": { "restore-cursor": "^2.0.0" @@ -3608,7 +3610,7 @@ "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", "dev": true, "requires": { "escape-string-regexp": "^1.0.5" @@ -3669,7 +3671,7 @@ "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", "dev": true }, "mimic-fn": { @@ -3687,13 +3689,13 @@ "mute-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "integrity": "sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ==", "dev": true }, "onetime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", "dev": true, "requires": { "mimic-fn": "^1.0.0" @@ -3702,7 +3704,7 @@ "restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", "dev": true, "requires": { "onetime": "^2.0.0", @@ -3728,7 +3730,7 @@ "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", "dev": true, "requires": { "ansi-regex": "^3.0.0" @@ -3737,7 +3739,7 @@ "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=", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "dev": true } } @@ -3776,13 +3778,13 @@ "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "integrity": "sha512-wFUFA5bg5dviipbQQ32yOQhl6gcJaJXiHE7dvR8VYPG97+J/GNC5FKGepKdEDUFeXRzDxPF1X/Btc8L+v7oqIQ==", "dev": true }, "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", "dev": true, "requires": { "restore-cursor": "^2.0.0" @@ -3873,7 +3875,7 @@ "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", "dev": true, "requires": { "escape-string-regexp": "^1.0.5" @@ -3956,7 +3958,7 @@ "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", "dev": true }, "locate-path": { @@ -3983,13 +3985,13 @@ "mute-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "integrity": "sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ==", "dev": true }, "onetime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", "dev": true, "requires": { "mimic-fn": "^1.0.0" @@ -4013,7 +4015,7 @@ "restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", "dev": true, "requires": { "onetime": "^2.0.0", @@ -4039,7 +4041,7 @@ "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", "dev": true, "requires": { "ansi-regex": "^3.0.0" @@ -4048,7 +4050,7 @@ "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=", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "dev": true } } @@ -4075,7 +4077,7 @@ "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "integrity": "sha512-wFUFA5bg5dviipbQQ32yOQhl6gcJaJXiHE7dvR8VYPG97+J/GNC5FKGepKdEDUFeXRzDxPF1X/Btc8L+v7oqIQ==", "dev": true } } @@ -4091,7 +4093,7 @@ "process-nextick-args": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + "integrity": "sha512-yN0WQmuCX63LP/TMvAg31nvT6m4vDqJEiiv2CAZqWOGNWutc9DfDk1NPYYmKUFmaVM2UwDowH4u5AHWYP/jxKw==" }, "progress": { "version": "2.0.3", @@ -4153,12 +4155,12 @@ "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" }, "qs": { "version": "0.6.6", "resolved": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz", - "integrity": "sha1-bgFQmP9RlouKPIGQAdXyyJvEsQc=" + "integrity": "sha512-kN+yNdAf29Jgp+AYHUmC7X4QdJPR8czuMWLNLc0aRxkQ7tB3vJQEONKKT9ou/rW7EbqVec11srC9q9BiVbcnHA==" }, "quick-lru": { "version": "4.0.1", @@ -4175,12 +4177,12 @@ "range-parser": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.0.tgz", - "integrity": "sha1-pLJkz+C+XONqvjdlrJwqJIdG28A=" + "integrity": "sha512-wOH5LIH2ZHo0P7/bwkR+aNbJ+kv3CHVX4B8qs9GqbtY29fi1bGPV5xczrutN20G+Z4XhRqRMTW3q0S4iyJJPfw==" }, "raven": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/raven/-/raven-1.1.3.tgz", - "integrity": "sha1-QnPBrm005CMPUbLAEEGjK5Iygio=", + "integrity": "sha512-RYov4wAaflZasWiCrZuizd3jNXxCOkW1WrXgWsGVb8kRpdHNZ+vPY27R6RhVtqzWp+DG9a5l6iP0QUPK4EgzaQ==", "requires": { "cookie": "0.3.1", "json-stringify-safe": "5.0.1", @@ -4192,19 +4194,19 @@ "cookie": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + "integrity": "sha512-+IJOX0OqlHCszo2mBUq+SrEbCj6w7Kpffqx60zYbPTFaO4+yYgRjHwcZNpWvaTylDHaV7PPmBHzSecZiMhtPgw==" }, "uuid": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.0.tgz", - "integrity": "sha1-Zyj8BFnEUNeWqZwxg3VpvfZy1yg=" + "integrity": "sha512-rqE1LoOVLv3QrZMjb4NkF5UWlkurCfPyItVnFPNKDDGkHw4dQUdE4zMcLqx28+0Kcf3+bnUk4PisaiRJT4aiaQ==" } } }, "raw-body": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", - "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=", + "integrity": "sha512-WmJJU2e9Y6M5UzTOkHaM7xJGAPQD8PNzx3bAd2+uhZAim6wDk6dAZxPVYLF67XhbR4hmKGh33Lpmh4XWrCH5Mg==", "requires": { "bytes": "1", "string_decoder": "0.10" @@ -4219,7 +4221,7 @@ "read-pkg": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "integrity": "sha512-eFIBOPW7FGjzBuk3hdXEuNSiTZS/xEMlH49HxMyzb0hyPfu4EhVjT2DH32K1hSSmVq4sebAWnZuuY5auISUTGA==", "dev": true, "requires": { "load-json-file": "^2.0.0", @@ -4230,7 +4232,7 @@ "read-pkg-up": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "integrity": "sha512-1orxQfbWGUiTn9XsPlChs6rLie/AV9jwZTGmu2NZw/CUDJQchXJFYE0Fq5j7+n558T1JhDWLdhyd1Zj+wLY//w==", "dev": true, "requires": { "find-up": "^2.0.0", @@ -4291,7 +4293,7 @@ "request": { "version": "2.34.0", "resolved": "https://registry.npmjs.org/request/-/request-2.34.0.tgz", - "integrity": "sha1-tdi5UmrdSi1GKfTUFxJFc5lkRa4=", + "integrity": "sha512-mD5mNhfkeaKMg5ZY/hZFbW4lyC/NTn34/ILGQr/XLSuxYOE6vJfL0MTPPXZcZrdt+Nh1Kce+f4B4KbGThIETxQ==", "dev": true, "requires": { "aws-sign2": "~0.5.0", @@ -4311,7 +4313,7 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true }, "require-in-the-middle": { @@ -4342,7 +4344,7 @@ "require-like": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz", - "integrity": "sha1-rW8wwTvs15cBDEaK+ndcDAprR/o=", + "integrity": "sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==", "dev": true }, "require-main-filename": { @@ -4354,7 +4356,7 @@ "require-relative": { "version": "0.8.7", "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz", - "integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=", + "integrity": "sha512-AKGr4qvHiryxRb19m3PsLRGuKVAbJLUD7E6eOaHkfKhwc+vSgVOCY5xNvm9EkolBKTOf0GrQAZKLimOCz81Khg==", "dev": true }, "require_optional": { @@ -4377,7 +4379,7 @@ "resolve-from": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", - "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" + "integrity": "sha512-qpFcKaXsq8+oRoLilkwyc7zHGF5i9Q2/25NIgLQQ/+VVv9rU4qvr6nXVAw1DsnXJyQkZsR4Ytfbtg5ehfcUssQ==" }, "restore-cursor": { "version": "3.1.0", @@ -4405,7 +4407,7 @@ "rimraf": { "version": "2.4.5", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", - "integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=", + "integrity": "sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ==", "optional": true, "requires": { "glob": "^6.0.1" @@ -4414,7 +4416,7 @@ "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "integrity": "sha512-Fx+QT3fGtS0jk8OvKyKgAB2YHPsrmqBRcMeTC5AZ+lp4vzXKPPrFSY3iLdgvjA3HVBkIvJeM6J80LRjx8bQwhA==", "dev": true, "requires": { "is-promise": "^2.1.0" @@ -4454,7 +4456,7 @@ "sandboxed-module": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/sandboxed-module/-/sandboxed-module-0.3.0.tgz", - "integrity": "sha1-8fvvvYCaT2kHO9B8rm/H2y6vX2o=", + "integrity": "sha512-/2IfB1wtca3eNVPXbQrb6UkhE/1pV4Wz+5CdG6DPYqeaDsYDzxglBT7/cVaqyrlRyQKdmw+uTZUTRos9FFD2PQ==", "dev": true, "requires": { "require-like": "0.1.2", @@ -4464,7 +4466,7 @@ "stack-trace": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.6.tgz", - "integrity": "sha1-HnGb1qJin/CcGJ4Xqe+QKpT8XbA=", + "integrity": "sha512-5/6uZt7RYjjAl8z2j1mXWAewz+I4Hk2/L/3n6NRLIQ31+uQ7nMd9O6G69QCdrrufHv0QGRRHl/jwUEGTqhelTA==", "dev": true } } @@ -4477,7 +4479,7 @@ "send": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/send/-/send-0.3.0.tgz", - "integrity": "sha1-lxgyRjSAb8dbxPj15R9X2dZmBuc=", + "integrity": "sha512-FPyeqtit9Z3zbusjv0KQyR8vQ9CL57qPNOz4GgcuIPSk+nx9WTUIMQoR6+0a7YOZpQVTtk04qH0IVQG3rohZ0Q==", "requires": { "buffer-crc32": "0.2.1", "debug": "0.8.0", @@ -4489,14 +4491,14 @@ "debug": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/debug/-/debug-0.8.0.tgz", - "integrity": "sha1-BUHqkfDlA/3wxe7UGKMlUCNJZ/A=" + "integrity": "sha512-jR+JRuwlhTwNPpLU6/JhiMydD6+GnL/33WE8LlmnBUqPHXkEpG2iNargYBO/Wxx7wXn7oxU6XwYIZyH4YuSW9Q==" } } }, "serve-static": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.1.0.tgz", - "integrity": "sha1-RU36Bbs93U5wGokVuDoniqkcVkM=", + "integrity": "sha512-vzgWiHz5xrM19pqugiYI6sWP9B0+K6vz4Ep5G1my9lVhuYkRXGYs5xtnXZ06fpLPRumROSZ1CLqiRxdngPkojQ==", "requires": { "parseurl": "1.0.1", "send": "0.3.0" @@ -4505,7 +4507,7 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true }, "settings-sharelatex": { @@ -4519,14 +4521,14 @@ "coffee-script": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.6.0.tgz", - "integrity": "sha1-gIs5bhEPU9AhoZpO8fZb4OjjX6M=" + "integrity": "sha512-Tx8itEfCsQp8RbLDFt7qwjqXycAx2g6SI7//4PPUR2j6meLmNifYm6zKrNDcU1+Q/GWRhjhEZk7DaLG1TfIzGA==" } } }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", "dev": true, "requires": { "shebang-regex": "^1.0.0" @@ -4535,7 +4537,7 @@ "shebang-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", "dev": true }, "shimmer": { @@ -4556,7 +4558,7 @@ "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "integrity": "sha512-meQNNykwecVxdu1RlYMKpQx4+wefIYpmxi6gexo/KAbwquJrBUrBmKYJrE8KFkVQAAVWEnwNdu21PgrD77J3xA==", "dev": true }, "sinon": { @@ -4585,13 +4587,13 @@ "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", "dev": true }, "path-to-regexp": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", - "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", + "integrity": "sha512-nifX1uj4S9IrK/w3Xe7kKvNEepXivANs9ng60Iq7PU/BlouV3yL/VUhFqTuTq33ykwUqoNcTeGo5vdOBP4jS/Q==", "dev": true, "requires": { "isarray": "0.0.1" @@ -4619,7 +4621,7 @@ "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", "dev": true } } @@ -4627,7 +4629,7 @@ "sntp": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", - "integrity": "sha1-+4hfGLDzqtGJ+CSGJTa87ux1CQA=", + "integrity": "sha512-bDLrKa/ywz65gCl+LmOiIhteP1bhEsAAzhfMedPoiHP3dyYnAevlaJshdqb9Yu0sRifyP/fRqSt8t+5qGIWlGQ==", "dev": true, "optional": true, "requires": { @@ -4682,7 +4684,7 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, "sshpk": { @@ -4712,24 +4714,24 @@ "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==" } } }, "stack-trace": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz", - "integrity": "sha1-qPbq7KkGdMMz58Q5U/J1tFFRBpU=" + "integrity": "sha512-vjUc6sfgtgY0dxCdnc40mK6Oftjo9+2K8H/NG81TMhgL392FtiPA9tn9RLyTxXmTLPJPjF3VyzFp6bsWFLisMQ==" }, "statsd-parser": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/statsd-parser/-/statsd-parser-0.0.4.tgz", - "integrity": "sha1-y9JDlTzELv/VSLXSI4jtaJ7GOb0=" + "integrity": "sha512-7XO+ur89EalMXXFQaydsczB8sclr5nDsNIoUu0IzJx1pIbHUhO3LtpSzBwetIuU9DyTLMiVaJBMtWS/Nb2KR4g==" }, "stream-shift": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + "integrity": "sha512-Afuc4BKirbx0fwm9bKOehZPG01DJkm/4qbklw4lo9nMPqd2x0kZTLcgwQUXdGiPPY489l3w8cQ5xEEAGbg8ACQ==" }, "string-width": { "version": "4.2.0", @@ -4790,7 +4792,7 @@ "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" }, "strip-ansi": { "version": "5.2.0", @@ -4812,7 +4814,7 @@ "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true }, "strip-json-comments": { @@ -4869,7 +4871,7 @@ "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", "dev": true }, "string-width": { @@ -4888,7 +4890,7 @@ "tdigest": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.1.tgz", - "integrity": "sha1-Ljyyw56kSeVdHmzZEReszKRYgCE=", + "integrity": "sha512-CXcDY/NIgIbKZPx5H4JJNpq6JwJhU5Z4+yWj4ZghDc7/9nVajiRlPPyMXRePPPlBfcayUqtoCXjo7/Hm82ecUA==", "requires": { "bintrees": "1.0.1" } @@ -4913,19 +4915,19 @@ "text-encoding": { "version": "0.6.4", "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", - "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", + "integrity": "sha512-hJnc6Qg3dWoOMkqP53F0dzRIgtmsAge09kxUIqGrEUS4qr5rWLckGYaQAVr+opBrIMRErGgy6f5aPnyPpyGRfg==", "dev": true }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" }, "through2": { "version": "2.0.5", @@ -4939,7 +4941,7 @@ "thunky": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-0.1.0.tgz", - "integrity": "sha1-vzAUaCTituZ7Dy16Ssi+smkIaE4=" + "integrity": "sha512-vquTt/sKNzFqFK8DKLg33U7deg93WKYH4CE2Ul9hOyMCfm7VXgM7GJQRpPAgnmgnrf407Fcq8TQVEKlbavAu+A==" }, "tmp": { "version": "0.0.33", @@ -4953,13 +4955,13 @@ "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true }, "to-mongodb-core": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-mongodb-core/-/to-mongodb-core-2.0.0.tgz", - "integrity": "sha1-NZbsdhOsmtO5ioncua77pWnNJ+s=" + "integrity": "sha512-vfXXcGYFP8+0L5IPOtUzzVIvPE/G3GN0TKa/PRBlzPqYyhm+UxhPmvv634EQgO4Ot8dHbBFihOslMJQclY8Z9A==" }, "tough-cookie": { "version": "2.3.4", @@ -4980,19 +4982,19 @@ "tunnel-agent": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.3.0.tgz", - "integrity": "sha1-rWgbaPUyGtKCfEz7G31d8s/pQu4=", + "integrity": "sha512-jlGqHGoKzyyjhwv/c9omAgohntThMcGtw8RV/RDLlkbbc08kni/akVxO62N8HaXMVbVsK1NCnpSK3N2xCt22ww==", "dev": true, "optional": true }, "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", "dev": true, "requires": { "prelude-ls": "~1.1.2" @@ -5001,7 +5003,7 @@ "type-detect": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", - "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", + "integrity": "sha512-5rqszGVwYgBoDkIm2oUtvkfZMQ0vk29iDMU0W2qCa3rG0vPDNczCMT4hV/bLBgLg8k8ri6+u3Zbt+S/14eMzlA==", "dev": true }, "type-fest": { @@ -5013,7 +5015,7 @@ "type-is": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.1.0.tgz", - "integrity": "sha1-0CReyLJnZmjVndDPMlUGBnalfbY=", + "integrity": "sha512-bGTRFAlk7i/YYyx/d1xYm6gLrALwTcY2HLwsVqAIPKJjjtlI/rGXRgjQrcOln2fcHCbAqi0hrueZ2yPnHvCipQ==", "requires": { "mime": "~1.2.11" } @@ -5027,7 +5029,7 @@ "underscore": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", - "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" + "integrity": "sha512-z4o1fvKUojIWh9XuaVLUDdf86RQiq13AC1dmHbTpoyuu+bquHms76v16CjycCbec87J7z0k//SiQVk0sMdFmpQ==" }, "uri-js": { "version": "4.2.2", @@ -5047,12 +5049,12 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "utils-merge": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", - "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=" + "integrity": "sha512-HwU9SLQEtyo+0uoKXd1nkLqigUWLB+QuNQR4OcmB73eWqksM5ovuqcycks2x043W8XVb75rG1HQ0h93TMXkzQQ==" }, "v8-compile-cache": { "version": "2.1.0", @@ -5073,7 +5075,7 @@ "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", "requires": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", @@ -5083,7 +5085,7 @@ "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==" } } }, @@ -5110,7 +5112,7 @@ "acorn-jsx": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "integrity": "sha512-AU7pnZkguthwBjKgCg6998ByQNIMjbuDQZ8bb78QAFZwPfmKia8AIzgY/gWgqCjnht8JLdXmB4YxA0KaV60ncQ==", "dev": true, "requires": { "acorn": "^3.0.4" @@ -5119,7 +5121,7 @@ "acorn": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "integrity": "sha512-OLUyIIZ7mF5oaAUT1w0TFqQS81q3saT46x8t7ukpPjMNk+nbs4ZHhs7ToV8EWnLYLepjETXd4XaCE4uxkMeqUw==", "dev": true } } @@ -5173,7 +5175,7 @@ "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", "dev": true }, "word-wrap": { @@ -5202,7 +5204,7 @@ "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", "dev": true }, "string-width": { @@ -5221,7 +5223,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "write": { "version": "1.0.3", @@ -5235,7 +5237,7 @@ "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + "integrity": "sha512-iTwvhNBRetXWe81+VcIw5YeadVSWyze7uA7nVnpP13ulrpnJ3UfQm5ApGnrkmxDJFdrblRdZs0EvaTCIfei5oQ==" }, "y18n": { "version": "4.0.0", @@ -5284,7 +5286,7 @@ "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", "dev": true }, "locate-path": { From 746791766c08e7ec17f6020578abeb67270af9ba Mon Sep 17 00:00:00 2001 From: Simon Detheridge <s@sd.ai> Date: Sun, 16 Feb 2020 14:06:37 +0000 Subject: [PATCH 24/27] Additional prettier fix --- services/docstore/app/js/MongoManager.js | 1 - 1 file changed, 1 deletion(-) diff --git a/services/docstore/app/js/MongoManager.js b/services/docstore/app/js/MongoManager.js index 413f60be82..66699c9ba3 100644 --- a/services/docstore/app/js/MongoManager.js +++ b/services/docstore/app/js/MongoManager.js @@ -162,7 +162,6 @@ module.exports = MongoManager = { ) } } - ;[ 'findDoc', 'getProjectsDocs', From cfad4b585dc86074191464bae82fc21b3bdef27f Mon Sep 17 00:00:00 2001 From: Simon Detheridge <s@sd.ai> Date: Sun, 16 Feb 2020 14:10:24 +0000 Subject: [PATCH 25/27] Fix linting errors missed by bulk-decaffienate --- services/docstore/app.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/services/docstore/app.js b/services/docstore/app.js index 725f1265c9..ebf7209b42 100644 --- a/services/docstore/app.js +++ b/services/docstore/app.js @@ -12,7 +12,6 @@ const express = require('express') const bodyParser = require('body-parser') const Errors = require('./app/js/Errors') const HttpController = require('./app/js/HttpController') -const Path = require('path') logger.initialize('docstore') if (Metrics.event_loop != null) { @@ -25,16 +24,16 @@ app.use(Metrics.http.monitor(logger)) Metrics.injectMetricsRoute(app) -app.param('project_id', function(req, res, next, project_id) { - if (project_id != null ? project_id.match(/^[0-9a-f]{24}$/) : undefined) { +app.param('project_id', function(req, res, next, projectId) { + if (projectId != null ? projectId.match(/^[0-9a-f]{24}$/) : undefined) { return next() } else { return next(new Error('invalid project id')) } }) -app.param('doc_id', function(req, res, next, doc_id) { - if (doc_id != null ? doc_id.match(/^[0-9a-f]{24}$/) : undefined) { +app.param('doc_id', function(req, res, next, docId) { + if (docId != null ? docId.match(/^[0-9a-f]{24}$/) : undefined) { return next() } else { return next(new Error('invalid doc id')) From e57545a532d87d57cbb8c8f7f94364e1b42a19bd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Nov 2019 11:33:46 +0000 Subject: [PATCH 26/27] Bump express from 4.1.2 to 4.5.0 Bumps [express](https://github.com/expressjs/express) from 4.1.2 to 4.5.0. - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/master/History.md) - [Commits](https://github.com/expressjs/express/compare/4.1.2...4.5.0) Signed-off-by: dependabot[bot] <support@github.com> --- services/docstore/package-lock.json | 236 +++++++++++++++++++++------- services/docstore/package.json | 2 +- 2 files changed, 182 insertions(+), 56 deletions(-) diff --git a/services/docstore/package-lock.json b/services/docstore/package-lock.json index fc2241cbd3..f878ea08df 100644 --- a/services/docstore/package-lock.json +++ b/services/docstore/package-lock.json @@ -529,12 +529,19 @@ } }, "accepts": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.0.1.tgz", - "integrity": "sha512-EsBDjbbGp44Tq6UGW6YE4cgD2xF1MIIyK7Vn+sElHW3EiSgqoIetsTiwFytb9YxODl6YVc4IIY28zeQ0JKGCLQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.0.7.tgz", + "integrity": "sha1-W1AftPBwQwmWTM2wSBclQSCNqxo=", "requires": { - "mime": "~1.2.11", - "negotiator": "~0.4.0" + "mime-types": "~1.0.0", + "negotiator": "0.4.7" + }, + "dependencies": { + "mime-types": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", + "integrity": "sha1-mVrhOSq4r/y/yyZB3QVOlDwNXc4=" + } } }, "acorn": { @@ -822,9 +829,9 @@ "integrity": "sha512-D8zmlb46xfuK2gGvKmUjIklQEouN2nQ0LEHHeZ/NoHM2LDiMk2EYzZ5Ntw/Urk+bgMDosOZxaRzXxvhI5TcAVQ==" }, "buffer-crc32": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.1.tgz", - "integrity": "sha512-vMfBIRp/wjlpueSz7Sb0OmO7C5SH58SSmbsT8G4D48YfO/Zgbr29xNXMpZVSC14ujVJfrZZH1Bl+kXYRQPuvfQ==" + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.3.tgz", + "integrity": "sha1-u1RRnpXRB8vSQA520MqxRnM22SE=" }, "buffer-equal-constant-time": { "version": "1.0.1", @@ -1044,12 +1051,12 @@ "cookie": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.2.tgz", - "integrity": "sha512-+mHmWbhevLwkiBf7QcbZXHr0v4ZQQ/OgHk3fsQHrsMMiGzuvAmU/YMUR+ZfrO/BLAGIWFfx2Z7Oyso0tZR/wiA==" + "integrity": "sha1-cv7D0k5Io0Mgc9kMEmQgBQYQBLE=" }, "cookie-signature": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.3.tgz", - "integrity": "sha512-/KzKzsm0OlguYov01OlOpTkX5MhBKUmfL/KMum7R80rPKheb9AwUzr78TwtBt1OdbnWrt4X+wxbTfcQ3noZqHw==" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.4.tgz", + "integrity": "sha1-Dt0iKG46ERuaKnDbNj6SXoZ/aso=" }, "core-js": { "version": "3.6.4", @@ -1114,9 +1121,19 @@ } }, "debug": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-0.8.1.tgz", - "integrity": "sha512-HlXEJm99YsRjLJ8xmuz0Lq8YUwrv7hAJkTEr6/Em3sUlSUNl0UdFA+1SrY4fnykeq1FVkUEUtwRGHs9VvlYbGA==" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.2.tgz", + "integrity": "sha1-OElZHBDM5khHbDx8Li40FttZY8Q=", + "requires": { + "ms": "0.6.2" + }, + "dependencies": { + "ms": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", + "integrity": "sha1-2JwhJMb9wTU9Zai3e/GqxLGTcIw=" + } + } }, "decamelize": { "version": "1.2.0", @@ -1160,6 +1177,11 @@ "dev": true, "optional": true }, + "depd": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-0.3.0.tgz", + "integrity": "sha1-Ecm8KOQlMl+9iziUC+/2n6UyaIM=" + }, "dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", @@ -1215,6 +1237,11 @@ "safe-buffer": "^5.0.1" } }, + "ee-first": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.0.3.tgz", + "integrity": "sha1-bJjECJq+y1p7hcGsRJqmA9Oz2r4=" + }, "emitter-listener": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/emitter-listener/-/emitter-listener-1.1.2.tgz", @@ -1304,7 +1331,7 @@ "escape-html": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz", - "integrity": "sha512-z6kAnok8fqVTra7Yu77dZF2Y6ETJlxH58wN38wNyuNQLm8xXdKnfNrlSmfXsTePWP03rRVUKHubtUwanwUi7+g==" + "integrity": "sha1-GBoobq05ejmpKFfPsdQwUuNWv/A=" }, "escape-string-regexp": { "version": "1.0.5", @@ -1766,27 +1793,48 @@ "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" }, "express": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.1.2.tgz", - "integrity": "sha512-U7G/TwoXu9uSHtGnvW6WQyLz3rP+qp3sHUiNpKw5Mz2o6DGenpxngH5tGnxgg09Hjqzje2CzZKukPoZfemepYQ==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.5.1.tgz", + "integrity": "sha1-S8Pm7J2yjldf5ZHDb7t4H/72/nw=", "requires": { - "accepts": "1.0.1", - "buffer-crc32": "0.2.1", + "accepts": "~1.0.7", + "buffer-crc32": "0.2.3", "cookie": "0.1.2", - "cookie-signature": "1.0.3", - "debug": ">= 0.7.3 < 1", + "cookie-signature": "1.0.4", + "debug": "1.0.2", + "depd": "0.3.0", "escape-html": "1.0.1", + "finalhandler": "0.0.2", "fresh": "0.2.2", + "media-typer": "0.2.0", "merge-descriptors": "0.0.2", - "methods": "0.1.0", + "methods": "1.0.1", "parseurl": "1.0.1", "path-to-regexp": "0.1.2", + "proxy-addr": "1.0.1", "qs": "0.6.6", "range-parser": "1.0.0", - "send": "0.3.0", - "serve-static": "1.1.0", - "type-is": "1.1.0", - "utils-merge": "1.0.0" + "send": "0.5.0", + "serve-static": "~1.3.0", + "type-is": "~1.3.2", + "utils-merge": "1.0.0", + "vary": "0.1.0" + }, + "dependencies": { + "mime-types": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", + "integrity": "sha1-mVrhOSq4r/y/yyZB3QVOlDwNXc4=" + }, + "type-is": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.3.2.tgz", + "integrity": "sha1-TypdxYd1yhYwJQr8cYb4s2MJ0bs=", + "requires": { + "media-typer": "0.2.0", + "mime-types": "~1.0.1" + } + } } }, "extend": { @@ -1860,6 +1908,15 @@ "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==" }, + "finalhandler": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.0.2.tgz", + "integrity": "sha1-BgPYde6H1WeiZmkoFcyK1E/M7to=", + "requires": { + "debug": "1.0.2", + "escape-html": "1.0.1" + } + }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", @@ -1874,6 +1931,14 @@ "resolved": "https://registry.npmjs.org/findit2/-/findit2-2.2.3.tgz", "integrity": "sha512-lg/Moejf4qXovVutL0Lz4IsaPoNYMuxt4PA0nGqFxnJ1CTTGGlEO2wKgoDpwknhvZ8k4Q2F+eesgkLbG2Mxfog==" }, + "finished": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/finished/-/finished-1.2.2.tgz", + "integrity": "sha1-QWCOr639ZWg7RqEiC8Sx7D2u3Ng=", + "requires": { + "ee-first": "1.0.3" + } + }, "flat-cache": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", @@ -1973,7 +2038,7 @@ "fresh": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.2.2.tgz", - "integrity": "sha512-ZGGi8GROK//ijm2gB33sUuN9TjN1tC/dvG4Bt4j6IWrVGpMmudUBCxx+Ir7qePsdREfkpQC4FL8W0jeSOsgv1w==" + "integrity": "sha1-lzHc9WeMf660T7kDxPct9VGH+nc=" }, "fs.realpath": { "version": "1.0.0", @@ -2334,6 +2399,11 @@ "side-channel": "^1.0.2" } }, + "ipaddr.js": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-0.1.2.tgz", + "integrity": "sha1-ah/T2FT1ACllw017vNm0qNSwRn4=" + }, "is": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/is/-/is-3.3.0.tgz", @@ -2875,10 +2945,15 @@ "integrity": "sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g==", "dev": true }, + "media-typer": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.2.0.tgz", + "integrity": "sha1-2KBlITrf6qLnYyGitt2jb/YzWYQ=" + }, "merge-descriptors": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-0.0.2.tgz", - "integrity": "sha512-dYBT4Ep+t/qnPeJcnMymmhTdd4g8/hn48ciaDqLAkfRf8abzLPS6Rb6EBdz5CZCL8tzZuI5ps9MhGQGxk+EuKg==" + "integrity": "sha1-w2pSp4FDdRPFcnXzndnTF1FKyMc=" }, "mersenne": { "version": "0.0.4", @@ -2909,9 +2984,9 @@ "dev": true }, "methods": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/methods/-/methods-0.1.0.tgz", - "integrity": "sha512-N4cn4CbDqu7Fp3AT4z3AsO19calgczhsmCGzXLCiUOrWg9sjb1B+yKFKOrnnPGKKvjyJBmw+k6b3adFN2LbuBw==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.0.1.tgz", + "integrity": "sha1-dbyRlD3/19oDfPPusO1zoAN80Us=" }, "metrics-sharelatex": { "version": "2.2.0", @@ -3155,9 +3230,9 @@ "optional": true }, "negotiator": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.9.tgz", - "integrity": "sha512-fvi5GQce2TGDzanaTxNY3bboxjdce18sqwNylY439wkEkiJIyTMhGFMdlPCvDsIPa9IKIfhKwCMWEQ9YpZgb1Q==" + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.7.tgz", + "integrity": "sha1-pBYPcXfsgGc4Yx0NMFIyXaQqvcg=" }, "nice-try": { "version": "1.0.5", @@ -3408,7 +3483,7 @@ "parseurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.0.1.tgz", - "integrity": "sha512-6W9+0+9Ihayqwjgp4OaLLqZ3KDtqPY2PtUPz8YNiy4PamjJv+7x6J9GO93O9rUZOLgaanTPxsKTasxqKkO1iSw==" + "integrity": "sha1-Llfc5u/dN8NRhwEDCUTCK/OIt7Q=" }, "path-exists": { "version": "3.0.0", @@ -3441,7 +3516,7 @@ "path-to-regexp": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.2.tgz", - "integrity": "sha512-BZU7Qr+qKkXJX9UBypMNikdZ85cQSjtfMhUykJFLJn4SNF0jhEbb9nMRpnNdA76ESryY8JpMA4k6XKdz3JS1pw==" + "integrity": "sha1-mysVH5zDAYye6lDKlXKeBXgXErQ=" }, "path-type": { "version": "2.0.0", @@ -4147,6 +4222,14 @@ } } }, + "proxy-addr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.0.1.tgz", + "integrity": "sha1-x8Vm1etOP61n7rnHfFVYzMObiKg=", + "requires": { + "ipaddr.js": "0.1.2" + } + }, "psl": { "version": "1.1.32", "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.32.tgz", @@ -4177,7 +4260,7 @@ "range-parser": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.0.tgz", - "integrity": "sha512-wOH5LIH2ZHo0P7/bwkR+aNbJ+kv3CHVX4B8qs9GqbtY29fi1bGPV5xczrutN20G+Z4XhRqRMTW3q0S4iyJJPfw==" + "integrity": "sha1-pLJkz+C+XONqvjdlrJwqJIdG28A=" }, "raven": { "version": "1.1.3", @@ -4477,31 +4560,69 @@ "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" }, "send": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.3.0.tgz", - "integrity": "sha512-FPyeqtit9Z3zbusjv0KQyR8vQ9CL57qPNOz4GgcuIPSk+nx9WTUIMQoR6+0a7YOZpQVTtk04qH0IVQG3rohZ0Q==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.5.0.tgz", + "integrity": "sha1-/A9+L5Limuv9ihst60o5TnpTGmg=", "requires": { - "buffer-crc32": "0.2.1", - "debug": "0.8.0", - "fresh": "~0.2.1", + "debug": "1.0.2", + "escape-html": "1.0.1", + "finished": "1.2.2", + "fresh": "0.2.2", "mime": "1.2.11", + "ms": "0.6.2", "range-parser": "~1.0.0" }, "dependencies": { - "debug": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-0.8.0.tgz", - "integrity": "sha512-jR+JRuwlhTwNPpLU6/JhiMydD6+GnL/33WE8LlmnBUqPHXkEpG2iNargYBO/Wxx7wXn7oxU6XwYIZyH4YuSW9Q==" + "ms": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", + "integrity": "sha1-2JwhJMb9wTU9Zai3e/GqxLGTcIw=" } } }, "serve-static": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.1.0.tgz", - "integrity": "sha512-vzgWiHz5xrM19pqugiYI6sWP9B0+K6vz4Ep5G1my9lVhuYkRXGYs5xtnXZ06fpLPRumROSZ1CLqiRxdngPkojQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.3.2.tgz", + "integrity": "sha1-2QSmy/VfURx4E49vRe5uadnRBco=", "requires": { - "parseurl": "1.0.1", - "send": "0.3.0" + "escape-html": "1.0.1", + "parseurl": "~1.1.3", + "send": "0.6.0" + }, + "dependencies": { + "debug": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.3.tgz", + "integrity": "sha1-/IxrLWACgEtAgcAgjg9kYLofo+Q=", + "requires": { + "ms": "0.6.2" + } + }, + "ms": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", + "integrity": "sha1-2JwhJMb9wTU9Zai3e/GqxLGTcIw=" + }, + "parseurl": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.1.3.tgz", + "integrity": "sha1-HwBXOKxxtBe8LQhFy9+iqLY+pjk=" + }, + "send": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.6.0.tgz", + "integrity": "sha1-pZ2pJl23w1FB4Qec8fNo7g1Zs6s=", + "requires": { + "debug": "1.0.3", + "depd": "0.3.0", + "escape-html": "1.0.1", + "finished": "1.2.2", + "fresh": "0.2.2", + "mime": "1.2.11", + "ms": "0.6.2", + "range-parser": "~1.0.0" + } + } } }, "set-blocking": { @@ -5054,7 +5175,7 @@ "utils-merge": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", - "integrity": "sha512-HwU9SLQEtyo+0uoKXd1nkLqigUWLB+QuNQR4OcmB73eWqksM5ovuqcycks2x043W8XVb75rG1HQ0h93TMXkzQQ==" + "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=" }, "v8-compile-cache": { "version": "2.1.0", @@ -5072,6 +5193,11 @@ "spdx-expression-parse": "^3.0.0" } }, + "vary": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/vary/-/vary-0.1.0.tgz", + "integrity": "sha1-3wlFiZ6TwMxb0YzIMh2dIedPYXY=" + }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", diff --git a/services/docstore/package.json b/services/docstore/package.json index a0b8b1e842..2b2c934d88 100644 --- a/services/docstore/package.json +++ b/services/docstore/package.json @@ -21,7 +21,7 @@ "dependencies": { "async": "~0.8.0", "body-parser": "~1.0.2", - "express": "~4.1.1", + "express": "~4.5.0", "logger-sharelatex": "^1.7.0", "metrics-sharelatex": "^2.2.0", "mongojs": "2.4.0", From fbece45717d973b370c176b98f596ba811a42945 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Nov 2019 11:33:46 +0000 Subject: [PATCH 27/27] Bump request from 2.34.0 to 2.47.0 Bumps [request](https://github.com/request/request) from 2.34.0 to 2.47.0. - [Release notes](https://github.com/request/request/releases) - [Changelog](https://github.com/request/request/blob/master/CHANGELOG.md) - [Commits](https://github.com/request/request/compare/v2.34.0...v2.47.0) Signed-off-by: dependabot[bot] <support@github.com> --- services/docstore/package-lock.json | 250 +++++++++++++++++----------- services/docstore/package.json | 2 +- 2 files changed, 155 insertions(+), 97 deletions(-) diff --git a/services/docstore/package-lock.json b/services/docstore/package-lock.json index f878ea08df..f241983350 100644 --- a/services/docstore/package-lock.json +++ b/services/docstore/package-lock.json @@ -531,7 +531,7 @@ "accepts": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.0.7.tgz", - "integrity": "sha1-W1AftPBwQwmWTM2wSBclQSCNqxo=", + "integrity": "sha512-iq8ew2zitUlNcUca0wye3fYwQ6sSPItDo38oC0R+XA5KTzeXRN+GF7NjOXs3dVItj4J+gQVdpq4/qbnMb1hMHw==", "requires": { "mime-types": "~1.0.0", "negotiator": "0.4.7" @@ -540,7 +540,7 @@ "mime-types": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", - "integrity": "sha1-mVrhOSq4r/y/yyZB3QVOlDwNXc4=" + "integrity": "sha512-echfutj/t5SoTL4WZpqjA1DCud1XO0WQF3/GJ48YBmc4ZMhCK77QA6Z/w6VTQERLKuJ4drze3kw2TUT8xZXVNw==" } } }, @@ -646,16 +646,14 @@ "asn1": { "version": "0.1.11", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", - "integrity": "sha512-Fh9zh3G2mZ8qM/kwsiKwL2U2FmXxVsboP4x1mXjnhKHv3SmzaBZoYvxEQJz/YS2gnCgd8xlAVWcZnQyC9qZBsA==", - "dev": true, - "optional": true + "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=", + "dev": true }, "assert-plus": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", - "integrity": "sha512-brU24g7ryhRwGCI2y+1dGQmQXiZF7TtIj583S96y0jjdajIe6wn8BuXyELYhvD22dtIxDQVFk04YTJwwdwOYJw==", - "dev": true, - "optional": true + "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=", + "dev": true }, "assertion-error": { "version": "1.0.0", @@ -697,9 +695,8 @@ "aws-sign2": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", - "integrity": "sha512-oqUX0DM5j7aPWPCnpWebiyNIj2wiNI87ZxnOMoGv0aE4TGlBy2N+5iWc6dQ/NOKZaBD2W6PVz8jtOGkWzSC5EA==", - "dev": true, - "optional": true + "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=", + "dev": true }, "aws4": { "version": "1.8.0", @@ -782,6 +779,35 @@ "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.1.tgz", "integrity": "sha512-tbaUB1QpTIj4cKY8c1rvNAvEQXA+ekzHmbe4jzNfW3QWsF9GnnP/BRWyl6/qqS53heoYJ93naaFcm/jooONH8g==" }, + "bl": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", + "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", + "dev": true, + "requires": { + "readable-stream": "~1.0.26" + }, + "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=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + } + } + }, "body-parser": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.0.2.tgz", @@ -801,9 +827,8 @@ "boom": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", - "integrity": "sha512-OvfN8y1oAxxphzkl2SnCS+ztV/uVKTATtgLjWYg/7KwcNyf3rzpHxNQJZCKtsZd4+MteKczhWbSjtEX4bGgU9g==", + "integrity": "sha1-emNune1O/O+xnO9JR6PGffrukRs=", "dev": true, - "optional": true, "requires": { "hoek": "0.9.x" } @@ -831,7 +856,7 @@ "buffer-crc32": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.3.tgz", - "integrity": "sha1-u1RRnpXRB8vSQA520MqxRnM22SE=" + "integrity": "sha512-HLvoSqq1z8fJEcT1lUlJZ4OJaXJZ1wsWm0+fBxkz9Bdf/WphA4Da7FtGUguNNyEXL4WB0hNMTaWmdFRFPy8YOQ==" }, "buffer-equal-constant-time": { "version": "1.0.1", @@ -1004,9 +1029,8 @@ "combined-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", - "integrity": "sha512-qfexlmLp9MyrkajQVyjEDb0Vj+KhRgR/rxLiVhaihlT+ZkX0lReqtH6Ack40CvMDERR4b5eFp3CreskpBs1Pig==", + "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", "dev": true, - "optional": true, "requires": { "delayed-stream": "0.0.5" } @@ -1051,12 +1075,12 @@ "cookie": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.2.tgz", - "integrity": "sha1-cv7D0k5Io0Mgc9kMEmQgBQYQBLE=" + "integrity": "sha512-+mHmWbhevLwkiBf7QcbZXHr0v4ZQQ/OgHk3fsQHrsMMiGzuvAmU/YMUR+ZfrO/BLAGIWFfx2Z7Oyso0tZR/wiA==" }, "cookie-signature": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.4.tgz", - "integrity": "sha1-Dt0iKG46ERuaKnDbNj6SXoZ/aso=" + "integrity": "sha512-k+lrG38ZC/S7zN6l1/HcF6xF4jMwkIUjnr5afDU7tzFxIfDmKzdqJdXo8HNYaXOuBJ3tPKxSiwCOTA0b3qQfaA==" }, "core-js": { "version": "3.6.4", @@ -1085,9 +1109,8 @@ "cryptiles": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", - "integrity": "sha512-gvWSbgqP+569DdslUiCelxIv3IYK5Lgmq1UrRnk+s1WxQOQ16j3GPDcjdtgL5Au65DU/xQi6q3xPtf5Kta+3IQ==", + "integrity": "sha1-7ZH/HxetE9N0gohZT4pIoNJvMlw=", "dev": true, - "optional": true, "requires": { "boom": "0.4.x" } @@ -1095,9 +1118,8 @@ "ctype": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", - "integrity": "sha512-T6CEkoSV4q50zW3TlTHMbzy1E5+zlnNcY+yb7tWVYlTwPhx9LpnfAkd4wecpWknDyptp4k97LUZeInlf6jdzBg==", - "dev": true, - "optional": true + "integrity": "sha1-gsGMJGH3QRTvFsE1IkrQuRRMoS8=", + "dev": true }, "damerau-levenshtein": { "version": "1.0.6", @@ -1123,7 +1145,7 @@ "debug": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.2.tgz", - "integrity": "sha1-OElZHBDM5khHbDx8Li40FttZY8Q=", + "integrity": "sha512-T9bufXIzQvCa4VrTIpLvvwdLhH+wuBtvIJJA3xgzVcaVETGmTIWMfEXQEd1K4p8BaRmQJPn6MPut38H7YQ+iIA==", "requires": { "ms": "0.6.2" }, @@ -1131,7 +1153,7 @@ "ms": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", - "integrity": "sha1-2JwhJMb9wTU9Zai3e/GqxLGTcIw=" + "integrity": "sha512-/pc3eh7TWorTtbvXg8je4GvrvEqCfH7PA3P7iW01yL2E53FKixzgMBaQi0NOPbMJqY34cBSvR0tZtmlTkdUG4A==" } } }, @@ -1173,14 +1195,13 @@ "delayed-stream": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", - "integrity": "sha512-v+7uBd1pqe5YtgPacIIbZ8HuHeLFVNe4mUEyFDXL6KiqzEykjbw+5mXZXpGFgNVasdL4jWKgaKIXrEHiynN1LA==", - "dev": true, - "optional": true + "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", + "dev": true }, "depd": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/depd/-/depd-0.3.0.tgz", - "integrity": "sha1-Ecm8KOQlMl+9iziUC+/2n6UyaIM=" + "integrity": "sha512-Uyx3FgdvEYlpA3W4lf37Ide++2qOsjLlJ7dap0tbM63j/BxTCcxmyIOO6PXbKbOuNSko+fsDHzzx1DUeo1+3fA==" }, "dlv": { "version": "1.1.3", @@ -1240,7 +1261,7 @@ "ee-first": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.0.3.tgz", - "integrity": "sha1-bJjECJq+y1p7hcGsRJqmA9Oz2r4=" + "integrity": "sha512-1q/3kz+ZwmrrWpJcCCrBZ3JnBzB1BMA5EVW9nxnIP1LxDZ16Cqs9VdolqLWlExet1vU+bar3WSkAa4/YrA9bIw==" }, "emitter-listener": { "version": "1.1.2", @@ -1331,7 +1352,7 @@ "escape-html": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.1.tgz", - "integrity": "sha1-GBoobq05ejmpKFfPsdQwUuNWv/A=" + "integrity": "sha512-z6kAnok8fqVTra7Yu77dZF2Y6ETJlxH58wN38wNyuNQLm8xXdKnfNrlSmfXsTePWP03rRVUKHubtUwanwUi7+g==" }, "escape-string-regexp": { "version": "1.0.5", @@ -1795,7 +1816,7 @@ "express": { "version": "4.5.1", "resolved": "https://registry.npmjs.org/express/-/express-4.5.1.tgz", - "integrity": "sha1-S8Pm7J2yjldf5ZHDb7t4H/72/nw=", + "integrity": "sha512-36quUqw4ZqgDnQzQpYLnNphPx612kfmQjbZlFt9Mz6Up/27IhkACtYBG9L/dAZkrXD0il3cq58DU+lpSL/Bg1g==", "requires": { "accepts": "~1.0.7", "buffer-crc32": "0.2.3", @@ -1824,12 +1845,12 @@ "mime-types": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", - "integrity": "sha1-mVrhOSq4r/y/yyZB3QVOlDwNXc4=" + "integrity": "sha512-echfutj/t5SoTL4WZpqjA1DCud1XO0WQF3/GJ48YBmc4ZMhCK77QA6Z/w6VTQERLKuJ4drze3kw2TUT8xZXVNw==" }, "type-is": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.3.2.tgz", - "integrity": "sha1-TypdxYd1yhYwJQr8cYb4s2MJ0bs=", + "integrity": "sha512-sdIhnvhWEyIP2DKjj1o9tL31m8vFxDfLPD56KXz2absqY5AF2QYkJC7Wrw2fkzsZA9mv+PCtgyB7EqYOgR+r3Q==", "requires": { "media-typer": "0.2.0", "mime-types": "~1.0.1" @@ -1911,7 +1932,7 @@ "finalhandler": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.0.2.tgz", - "integrity": "sha1-BgPYde6H1WeiZmkoFcyK1E/M7to=", + "integrity": "sha512-SbpQfvWVwWEBlPTQyaM9gs0D5404ENTC0x2jzbb7t+P+EOD/cBlWjAAvfozIQYtOepUuNkxoLNLCK9/kS29f4w==", "requires": { "debug": "1.0.2", "escape-html": "1.0.1" @@ -1934,7 +1955,7 @@ "finished": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/finished/-/finished-1.2.2.tgz", - "integrity": "sha1-QWCOr639ZWg7RqEiC8Sx7D2u3Ng=", + "integrity": "sha512-HPJ8x7Gn1pmTS1zWyMoXmQ1yxHkYHRoFsBI66ONq4PS9iWBJy1iHYXOSqMWNp3ksMXfrBpenkSwBhl9WG4zr4Q==", "requires": { "ee-first": "1.0.3" } @@ -2002,15 +2023,14 @@ "forever-agent": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", - "integrity": "sha512-PDG5Ef0Dob/JsZUxUltJOhm/Y9mlteAE+46y3M9RBz/Rd3QVENJ75aGRhN56yekTUboaBIkd8KVWX2NjF6+91A==", + "integrity": "sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA=", "dev": true }, "form-data": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", - "integrity": "sha512-x8eE+nzFtAMA0YYlSxf/Qhq6vP1f8wSoZ7Aw1GuctBcmudCNuTUmmx45TfEplyb6cjsZO/jvh6+1VpZn24ez+w==", + "integrity": "sha1-kavXiKupcCsaq/qLwBAxoqyeOxI=", "dev": true, - "optional": true, "requires": { "async": "~0.9.0", "combined-stream": "~0.0.4", @@ -2020,9 +2040,8 @@ "async": { "version": "0.9.2", "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha512-l6ToIJIotphWahxxHyzK9bnLR6kM4jJIIgLShZeqLY7iboHoGkdgFl7W2/Ivi4SkMJYGKqW8vSuk0uKUj6qsSw==", - "dev": true, - "optional": true + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true } } }, @@ -2038,7 +2057,7 @@ "fresh": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.2.2.tgz", - "integrity": "sha1-lzHc9WeMf660T7kDxPct9VGH+nc=" + "integrity": "sha512-ZGGi8GROK//ijm2gB33sUuN9TjN1tC/dvG4Bt4j6IWrVGpMmudUBCxx+Ir7qePsdREfkpQC4FL8W0jeSOsgv1w==" }, "fs.realpath": { "version": "1.0.0", @@ -2236,11 +2255,10 @@ "dev": true }, "hawk": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.0.0.tgz", - "integrity": "sha512-Sg+VzrI7TjUomO0rjD6UXawsj50ykn5sB/xKNW/IenxzRVyw/wt9A2FLzYpGL/r0QG5hyXY8nLx/2m8UutoDcg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", + "integrity": "sha1-h81JH5tG5OKurKM1QWdmiF0tHtk=", "dev": true, - "optional": true, "requires": { "boom": "0.4.x", "cryptiles": "0.2.x", @@ -2262,9 +2280,8 @@ "hoek": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", - "integrity": "sha512-ZZ6eGyzGjyMTmpSPYVECXy9uNfqBR7x5CavhUaLOeD6W0vWK1mp/b7O3f86XE0Mtfo9rZ6Bh3fnuw9Xr8MF9zA==", - "dev": true, - "optional": true + "integrity": "sha1-PTIkYrrfB3Fup+uFuviAec3c5QU=", + "dev": true }, "hosted-git-info": { "version": "2.8.5", @@ -2275,9 +2292,8 @@ "http-signature": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", - "integrity": "sha512-coK8uR5rq2IMj+Hen+sKPA5ldgbCc1/spPdKCL1Fw6h+D0s/2LzMcRK0Cqufs1h0ryx/niwBHGFu8HC3hwU+lA==", + "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", "dev": true, - "optional": true, "requires": { "asn1": "0.1.11", "assert-plus": "^0.1.5", @@ -2399,10 +2415,16 @@ "side-channel": "^1.0.2" } }, + "ip-regex": { + "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": "0.1.2", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-0.1.2.tgz", - "integrity": "sha1-ah/T2FT1ACllw017vNm0qNSwRn4=" + "integrity": "sha512-MGrEjHz4Hk5UVpJXZQ2tHB+bp6xgdRKCAEWdrgFsoAmXCgKAPtj8LqMxgvlWEAj9aN+PpTcvE051uZU3K3kLSQ==" }, "is": { "version": "3.3.0", @@ -2948,12 +2970,12 @@ "media-typer": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.2.0.tgz", - "integrity": "sha1-2KBlITrf6qLnYyGitt2jb/YzWYQ=" + "integrity": "sha512-TSggxYk75oP4tae7JkT8InpcFGUP4340zg1dOWjcu9qcphaDKtXEuNUv3OD4vJ+gVTvIDK797W0uYeNm8qqsDg==" }, "merge-descriptors": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-0.0.2.tgz", - "integrity": "sha1-w2pSp4FDdRPFcnXzndnTF1FKyMc=" + "integrity": "sha512-dYBT4Ep+t/qnPeJcnMymmhTdd4g8/hn48ciaDqLAkfRf8abzLPS6Rb6EBdz5CZCL8tzZuI5ps9MhGQGxk+EuKg==" }, "mersenne": { "version": "0.0.4", @@ -2986,7 +3008,7 @@ "methods": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/methods/-/methods-1.0.1.tgz", - "integrity": "sha1-dbyRlD3/19oDfPPusO1zoAN80Us=" + "integrity": "sha512-2403MfnVypWSNIEpmQ26/ObZ5kSUx37E8NHRvriw0+I8Sne7k0HGuLGCk0OrCqURh4UIygD0cSsYq+Ll+kzNqA==" }, "metrics-sharelatex": { "version": "2.2.0", @@ -3232,7 +3254,7 @@ "negotiator": { "version": "0.4.7", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.4.7.tgz", - "integrity": "sha1-pBYPcXfsgGc4Yx0NMFIyXaQqvcg=" + "integrity": "sha512-ujxWwyRfZ6udAgHGECQC3JDO9e6UAsuItfUMcqA0Xf2OLNQTveFVFx+fHGIJ5p0MJaJrZyGQqPwzuN0NxJzEKA==" }, "nice-try": { "version": "1.0.5", @@ -3283,7 +3305,7 @@ "node-uuid": { "version": "1.4.8", "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", - "integrity": "sha512-TkCET/3rr9mUuRp+CpO7qfgT++aAxfDRaalQhwPFzI9BY/2rCDn6OfpZOVggi1AXfTPpfkTrg5f5WQx5G1uLxA==", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", "dev": true }, "normalize-package-data": { @@ -3299,11 +3321,10 @@ } }, "oauth-sign": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz", - "integrity": "sha512-Tr31Sh5FnK9YKm7xTUPyDMsNOvMqkVDND0zvK/Wgj7/H9q8mpye0qG2nVzrnsvLhcsX5DtqXD0la0ks6rkPCGQ==", - "dev": true, - "optional": true + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.4.0.tgz", + "integrity": "sha1-8ilW8x6nFRqCHl8vsywRPK2Ln2k=", + "dev": true }, "object-assign": { "version": "4.1.1", @@ -3483,7 +3504,7 @@ "parseurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.0.1.tgz", - "integrity": "sha1-Llfc5u/dN8NRhwEDCUTCK/OIt7Q=" + "integrity": "sha512-6W9+0+9Ihayqwjgp4OaLLqZ3KDtqPY2PtUPz8YNiy4PamjJv+7x6J9GO93O9rUZOLgaanTPxsKTasxqKkO1iSw==" }, "path-exists": { "version": "3.0.0", @@ -3516,7 +3537,7 @@ "path-to-regexp": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.2.tgz", - "integrity": "sha1-mysVH5zDAYye6lDKlXKeBXgXErQ=" + "integrity": "sha512-BZU7Qr+qKkXJX9UBypMNikdZ85cQSjtfMhUykJFLJn4SNF0jhEbb9nMRpnNdA76ESryY8JpMA4k6XKdz3JS1pw==" }, "path-type": { "version": "2.0.0", @@ -4225,7 +4246,7 @@ "proxy-addr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.0.1.tgz", - "integrity": "sha1-x8Vm1etOP61n7rnHfFVYzMObiKg=", + "integrity": "sha512-rIUGzBlSfkJMWWCgsd4N5wvVSNAcJZg//UwPZumDIbScHRUzuSOjBmIdyICiKkB9yArv+er9qC6RA/NL3AWc6A==", "requires": { "ipaddr.js": "0.1.2" } @@ -4260,7 +4281,7 @@ "range-parser": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.0.tgz", - "integrity": "sha1-pLJkz+C+XONqvjdlrJwqJIdG28A=" + "integrity": "sha512-wOH5LIH2ZHo0P7/bwkR+aNbJ+kv3CHVX4B8qs9GqbtY29fi1bGPV5xczrutN20G+Z4XhRqRMTW3q0S4iyJJPfw==" }, "raven": { "version": "1.1.3", @@ -4374,23 +4395,47 @@ "dev": true }, "request": { - "version": "2.34.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.34.0.tgz", - "integrity": "sha512-mD5mNhfkeaKMg5ZY/hZFbW4lyC/NTn34/ILGQr/XLSuxYOE6vJfL0MTPPXZcZrdt+Nh1Kce+f4B4KbGThIETxQ==", + "version": "2.47.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.47.0.tgz", + "integrity": "sha1-Cen9Gk/tZZOoBe+CArIPDF7LSF8=", "dev": true, "requires": { "aws-sign2": "~0.5.0", + "bl": "~0.9.0", + "caseless": "~0.6.0", + "combined-stream": "~0.0.5", "forever-agent": "~0.5.0", "form-data": "~0.1.0", - "hawk": "~1.0.0", + "hawk": "1.1.1", "http-signature": "~0.10.0", "json-stringify-safe": "~5.0.0", - "mime": "~1.2.9", + "mime-types": "~1.0.1", "node-uuid": "~1.4.0", - "oauth-sign": "~0.3.0", - "qs": "~0.6.0", + "oauth-sign": "~0.4.0", + "qs": "~2.3.1", + "stringstream": "~0.0.4", "tough-cookie": ">=0.12.0", - "tunnel-agent": "~0.3.0" + "tunnel-agent": "~0.4.0" + }, + "dependencies": { + "caseless": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.6.0.tgz", + "integrity": "sha1-gWfBq4OX+1u5X5bSjlqBxQ8kesQ=", + "dev": true + }, + "mime-types": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", + "integrity": "sha1-mVrhOSq4r/y/yyZB3QVOlDwNXc4=", + "dev": true + }, + "qs": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", + "integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=", + "dev": true + } } }, "require-directory": { @@ -4562,7 +4607,7 @@ "send": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/send/-/send-0.5.0.tgz", - "integrity": "sha1-/A9+L5Limuv9ihst60o5TnpTGmg=", + "integrity": "sha512-uuPWJQK6p0btveYhOxRqvcB9Cfcs9ugNrMd0SoM/tqzOC9A86bX4rDEQN84X3Cc5Gpo5Az2cB4Olo5c3Aso2Sg==", "requires": { "debug": "1.0.2", "escape-html": "1.0.1", @@ -4576,14 +4621,14 @@ "ms": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", - "integrity": "sha1-2JwhJMb9wTU9Zai3e/GqxLGTcIw=" + "integrity": "sha512-/pc3eh7TWorTtbvXg8je4GvrvEqCfH7PA3P7iW01yL2E53FKixzgMBaQi0NOPbMJqY34cBSvR0tZtmlTkdUG4A==" } } }, "serve-static": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.3.2.tgz", - "integrity": "sha1-2QSmy/VfURx4E49vRe5uadnRBco=", + "integrity": "sha512-KwjCeYUx7IM1neg8/P0+O1DZsl76XcOSuV0ZxrI0r60vwGlcjMjKOYCK/OFLJy/a2CFuIyAa/x0PuQ0yuG+IgQ==", "requires": { "escape-html": "1.0.1", "parseurl": "~1.1.3", @@ -4593,7 +4638,7 @@ "debug": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.3.tgz", - "integrity": "sha1-/IxrLWACgEtAgcAgjg9kYLofo+Q=", + "integrity": "sha512-MltK7Ykj/udtD728gD/RrONStwVnDpBNIP1h+CBcnwnJdHqHxfWHI1E8XLootUl7NOPAYTCCXlb8/Qmy7WyB1w==", "requires": { "ms": "0.6.2" } @@ -4601,17 +4646,17 @@ "ms": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", - "integrity": "sha1-2JwhJMb9wTU9Zai3e/GqxLGTcIw=" + "integrity": "sha512-/pc3eh7TWorTtbvXg8je4GvrvEqCfH7PA3P7iW01yL2E53FKixzgMBaQi0NOPbMJqY34cBSvR0tZtmlTkdUG4A==" }, "parseurl": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.1.3.tgz", - "integrity": "sha1-HwBXOKxxtBe8LQhFy9+iqLY+pjk=" + "integrity": "sha512-7y9IL/9x2suvr1uIvoAc3yv3f28hZ55g2OM+ybEtnZqV6Ykeg36sy1PCsTN9rQUZYzb9lTKLzzmJM11jaXSloA==" }, "send": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/send/-/send-0.6.0.tgz", - "integrity": "sha1-pZ2pJl23w1FB4Qec8fNo7g1Zs6s=", + "integrity": "sha512-A3EwHmDwcPcmLxIRNjr2YbXiYWq6M9JyUq4303pLKVFs4m5oeME0a9Cpcu9N22fED5XVepldjPYGo9eJifb7Yg==", "requires": { "debug": "1.0.3", "depd": "0.3.0", @@ -4750,9 +4795,8 @@ "sntp": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", - "integrity": "sha512-bDLrKa/ywz65gCl+LmOiIhteP1bhEsAAzhfMedPoiHP3dyYnAevlaJshdqb9Yu0sRifyP/fRqSt8t+5qGIWlGQ==", + "integrity": "sha1-+4hfGLDzqtGJ+CSGJTa87ux1CQA=", "dev": true, - "optional": true, "requires": { "hoek": "0.9.x" } @@ -4915,6 +4959,12 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" }, + "stringstream": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", + "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", + "dev": true + }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", @@ -5085,13 +5135,22 @@ "integrity": "sha512-vfXXcGYFP8+0L5IPOtUzzVIvPE/G3GN0TKa/PRBlzPqYyhm+UxhPmvv634EQgO4Ot8dHbBFihOslMJQclY8Z9A==" }, "tough-cookie": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", - "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz", + "integrity": "sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==", "dev": true, - "optional": true, "requires": { - "punycode": "^1.4.1" + "ip-regex": "^2.1.0", + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + } } }, "tslib": { @@ -5101,11 +5160,10 @@ "dev": true }, "tunnel-agent": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.3.0.tgz", - "integrity": "sha512-jlGqHGoKzyyjhwv/c9omAgohntThMcGtw8RV/RDLlkbbc08kni/akVxO62N8HaXMVbVsK1NCnpSK3N2xCt22ww==", - "dev": true, - "optional": true + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true }, "tweetnacl": { "version": "0.14.5", @@ -5175,7 +5233,7 @@ "utils-merge": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", - "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=" + "integrity": "sha512-HwU9SLQEtyo+0uoKXd1nkLqigUWLB+QuNQR4OcmB73eWqksM5ovuqcycks2x043W8XVb75rG1HQ0h93TMXkzQQ==" }, "v8-compile-cache": { "version": "2.1.0", @@ -5196,7 +5254,7 @@ "vary": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/vary/-/vary-0.1.0.tgz", - "integrity": "sha1-3wlFiZ6TwMxb0YzIMh2dIedPYXY=" + "integrity": "sha512-tyyeG46NQdwyVP/RsWLSrT78ouwEuvwk9gK8vQK4jdXmqoXtTXW+vsCfNcnqRhigF8olV34QVZarmAi6wBV2Mw==" }, "verror": { "version": "1.10.0", diff --git a/services/docstore/package.json b/services/docstore/package.json index 2b2c934d88..82d2e34426 100644 --- a/services/docstore/package.json +++ b/services/docstore/package.json @@ -50,7 +50,7 @@ "mocha": "^4.0.1", "prettier": "^1.19.1", "prettier-eslint-cli": "^5.0.0", - "request": "~2.34.0", + "request": "~2.47.0", "sandboxed-module": "~0.3.0", "sinon": "~3.2.1" },