diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..d19812c3 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea/** \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 4b1147d4..00000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "type": "chrome", - "request": "launch", - "name": "Launch Chrome against localhost", - "url": "http://localhost:3000", - "webRoot": "${workspaceFolder}" - } - ] -} diff --git a/README.md b/README.md index dd70f9af..72535c6d 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ ## Snug 사용법 -### Snug 주소 : 준비중 +### Snug 주소 : [바로가기](http://45.119.147.186:3000/) ### 기능설명 WIKI : 준비중 @@ -76,10 +76,7 @@ #### 주역할 - Snug 팀을 이끄는 정신적 지주 -- 프론트엔드에서 재사용 가능한 Component를 고민했습니다. -- 재사용 가능한 Component를 활용해 화면을 구성하는 방법에 대하여 고민했습니다. -- 우리 프로젝트에 알맞는 여러가지 Custom Component를 작성했습니다. -- 프론트엔드에서 효과적인 데이터 흐름 제어를 고민했습니다. (Context Api) +- 프론트엔드에서 재사용 가능한 Component를 고민했습니다. - 팀원들을 질문으로 괴롭혔습니다. - **커스터마이징 가능한 컴포넌트 구현** diff --git a/client/package-lock.json b/client/package-lock.json index b711408b..b96dc2c2 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -60,72 +60,354 @@ } }, "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.7.0.tgz", - "integrity": "sha512-Cd8r8zs4RKDwMG/92lpZcnn5WPQ3LAMQbCw42oqUh4s7vsSN5ANUZjMel0OOnxDLq57hoDDbai+ryygYfCTOsw==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.7.4.tgz", + "integrity": "sha512-Biq/d/WtvfftWZ9Uf39hbPBYDUo986m5Bb4zhkeYDGUllF43D+nUe5M6Vuo6/8JDK/0YX/uBdeoQpyaNhNugZQ==", "requires": { - "@babel/helper-explode-assignable-expression": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/helper-explode-assignable-expression": "^7.7.4", + "@babel/types": "^7.7.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-builder-react-jsx": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.7.0.tgz", - "integrity": "sha512-LSln3cexwInTMYYoFeVLKnYPPMfWNJ8PubTBs3hkh7wCu9iBaqq1OOyW+xGmEdLxT1nhsl+9SJ+h2oUDYz0l2A==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.7.4.tgz", + "integrity": "sha512-kvbfHJNN9dg4rkEM4xn1s8d1/h6TYNvajy9L1wx4qLn9HFg0IkTsQi4rfBe92nxrPUFcMsHoMV+8rU7MJb3fCA==", "requires": { - "@babel/types": "^7.7.0", + "@babel/types": "^7.7.4", "esutils": "^2.0.0" + }, + "dependencies": { + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-call-delegate": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.7.0.tgz", - "integrity": "sha512-Su0Mdq7uSSWGZayGMMQ+z6lnL00mMCnGAbO/R0ZO9odIdB/WNU/VfQKqMQU0fdIsxQYbRjDM4BixIa93SQIpvw==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.7.4.tgz", + "integrity": "sha512-8JH9/B7J7tCYJ2PpWVpw9JhPuEVHztagNVuQAFBVFYluRMlpG7F1CgKEgGeL6KFqcsIa92ZYVj6DSc0XwmN1ZA==", "requires": { - "@babel/helper-hoist-variables": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/helper-hoist-variables": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@babel/types": "^7.7.4" + }, + "dependencies": { + "@babel/generator": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.4.tgz", + "integrity": "sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg==", + "requires": { + "@babel/types": "^7.7.4", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + } + }, + "@babel/helper-function-name": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz", + "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==", + "requires": { + "@babel/helper-get-function-arity": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz", + "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz", + "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/parser": { + "version": "7.7.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.5.tgz", + "integrity": "sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig==" + }, + "@babel/template": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz", + "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/traverse": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz", + "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==", + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.7.4", + "@babel/helper-function-name": "^7.7.4", + "@babel/helper-split-export-declaration": "^7.7.4", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } + }, + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-create-class-features-plugin": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.7.0.tgz", - "integrity": "sha512-MZiB5qvTWoyiFOgootmRSDV1udjIqJW/8lmxgzKq6oDqxdmHUjeP2ZUOmgHdYjmUVNABqRrHjYAYRvj8Eox/UA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.7.4.tgz", + "integrity": "sha512-l+OnKACG4uiDHQ/aJT8dwpR+LhCJALxL0mJ6nzjB25e5IPwqV1VOsY7ah6UB1DG+VOXAIMtuC54rFJGiHkxjgA==", "requires": { - "@babel/helper-function-name": "^7.7.0", - "@babel/helper-member-expression-to-functions": "^7.7.0", - "@babel/helper-optimise-call-expression": "^7.7.0", + "@babel/helper-function-name": "^7.7.4", + "@babel/helper-member-expression-to-functions": "^7.7.4", + "@babel/helper-optimise-call-expression": "^7.7.4", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.7.0", - "@babel/helper-split-export-declaration": "^7.7.0" + "@babel/helper-replace-supers": "^7.7.4", + "@babel/helper-split-export-declaration": "^7.7.4" + }, + "dependencies": { + "@babel/helper-function-name": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz", + "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==", + "requires": { + "@babel/helper-get-function-arity": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz", + "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz", + "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/parser": { + "version": "7.7.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.5.tgz", + "integrity": "sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig==" + }, + "@babel/template": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz", + "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-create-regexp-features-plugin": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.7.2.tgz", - "integrity": "sha512-pAil/ZixjTlrzNpjx+l/C/wJk002Wo7XbbZ8oujH/AoJ3Juv0iN/UTcPUHXKMFLqsfS0Hy6Aow8M31brUYBlQQ==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.7.4.tgz", + "integrity": "sha512-Mt+jBKaxL0zfOIWrfQpnfYCN7/rS6GKx6CCCfuoqVVd+17R8zNDlzVYmIi9qyb2wOk002NsmSTDymkIygDUH7A==", "requires": { "@babel/helper-regex": "^7.4.4", "regexpu-core": "^4.6.0" } }, "@babel/helper-define-map": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.7.0.tgz", - "integrity": "sha512-kPKWPb0dMpZi+ov1hJiwse9dWweZsz3V9rP4KdytnX1E7z3cTNmFGglwklzFPuqIcHLIY3bgKSs4vkwXXdflQA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.7.4.tgz", + "integrity": "sha512-v5LorqOa0nVQUvAUTUF3KPastvUt/HzByXNamKQ6RdJRTV7j8rLL+WB5C/MzzWAwOomxDhYFb1wLLxHqox86lg==", "requires": { - "@babel/helper-function-name": "^7.7.0", - "@babel/types": "^7.7.0", + "@babel/helper-function-name": "^7.7.4", + "@babel/types": "^7.7.4", "lodash": "^4.17.13" + }, + "dependencies": { + "@babel/helper-function-name": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz", + "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==", + "requires": { + "@babel/helper-get-function-arity": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz", + "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/parser": { + "version": "7.7.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.5.tgz", + "integrity": "sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig==" + }, + "@babel/template": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz", + "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-explode-assignable-expression": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.7.0.tgz", - "integrity": "sha512-CDs26w2shdD1urNUAji2RJXyBFCaR+iBEGnFz3l7maizMkQe3saVw9WtjG1tz8CwbjvlFnaSLVhgnu1SWaherg==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.7.4.tgz", + "integrity": "sha512-2/SicuFrNSXsZNBxe5UGdLr+HZg+raWBLE9vC98bdYOKX/U6PY0mdGlYUJdtTDPSU0Lw0PNbKKDpwYHJLn2jLg==", "requires": { - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/traverse": "^7.7.4", + "@babel/types": "^7.7.4" + }, + "dependencies": { + "@babel/generator": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.4.tgz", + "integrity": "sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg==", + "requires": { + "@babel/types": "^7.7.4", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + } + }, + "@babel/helper-function-name": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz", + "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==", + "requires": { + "@babel/helper-get-function-arity": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz", + "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz", + "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/parser": { + "version": "7.7.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.5.tgz", + "integrity": "sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig==" + }, + "@babel/template": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz", + "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/traverse": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz", + "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==", + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.7.4", + "@babel/helper-function-name": "^7.7.4", + "@babel/helper-split-export-declaration": "^7.7.4", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } + }, + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-function-name": { @@ -147,19 +429,43 @@ } }, "@babel/helper-hoist-variables": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.7.0.tgz", - "integrity": "sha512-LUe/92NqsDAkJjjCEWkNe+/PcpnisvnqdlRe19FahVapa4jndeuJ+FBiTX1rcAKWKcJGE+C3Q3tuEuxkSmCEiQ==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.7.4.tgz", + "integrity": "sha512-wQC4xyvc1Jo/FnLirL6CEgPgPCa8M74tOdjWpRhQYapz5JC7u3NYU1zCVoVAGCE3EaIP9T1A3iW0WLJ+reZlpQ==", "requires": { - "@babel/types": "^7.7.0" + "@babel/types": "^7.7.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-member-expression-to-functions": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.7.0.tgz", - "integrity": "sha512-QaCZLO2RtBcmvO/ekOLp8p7R5X2JriKRizeDpm5ChATAFWrrYDcDxPuCIBXKyBjY+i1vYSdcUTMIb8psfxHDPA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.7.4.tgz", + "integrity": "sha512-9KcA1X2E3OjXl/ykfMMInBK+uVdfIVakVe7W7Lg3wfXUNyS3Q1HWLFRwZIjhqiCGbslummPDnmb7vIekS0C1vw==", "requires": { - "@babel/types": "^7.7.0" + "@babel/types": "^7.7.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-module-imports": { @@ -171,24 +477,79 @@ } }, "@babel/helper-module-transforms": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.7.0.tgz", - "integrity": "sha512-rXEefBuheUYQyX4WjV19tuknrJFwyKw0HgzRwbkyTbB+Dshlq7eqkWbyjzToLrMZk/5wKVKdWFluiAsVkHXvuQ==", - "requires": { - "@babel/helper-module-imports": "^7.7.0", - "@babel/helper-simple-access": "^7.7.0", - "@babel/helper-split-export-declaration": "^7.7.0", - "@babel/template": "^7.7.0", - "@babel/types": "^7.7.0", + "version": "7.7.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.7.5.tgz", + "integrity": "sha512-A7pSxyJf1gN5qXVcidwLWydjftUN878VkalhXX5iQDuGyiGK3sOrrKKHF4/A4fwHtnsotv/NipwAeLzY4KQPvw==", + "requires": { + "@babel/helper-module-imports": "^7.7.4", + "@babel/helper-simple-access": "^7.7.4", + "@babel/helper-split-export-declaration": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/types": "^7.7.4", "lodash": "^4.17.13" + }, + "dependencies": { + "@babel/helper-module-imports": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.7.4.tgz", + "integrity": "sha512-dGcrX6K9l8258WFjyDLJwuVKxR4XZfU0/vTUgOQYWEnRD8mgr+p4d6fCUMq/ys0h4CCt/S5JhbvtyErjWouAUQ==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz", + "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/parser": { + "version": "7.7.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.5.tgz", + "integrity": "sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig==" + }, + "@babel/template": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz", + "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-optimise-call-expression": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.7.0.tgz", - "integrity": "sha512-48TeqmbazjNU/65niiiJIJRc5JozB8acui1OS7bSd6PgxfuovWsvjfWSzlgx+gPFdVveNzUdpdIg5l56Pl5jqg==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.7.4.tgz", + "integrity": "sha512-VB7gWZ2fDkSuqW6b1AKXkJWO5NyNI3bFL/kK79/30moK57blr6NbH8xcl2XcKCwOmJosftWunZqfO84IGq3ZZg==", "requires": { - "@babel/types": "^7.7.0" + "@babel/types": "^7.7.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-plugin-utils": { @@ -205,35 +566,230 @@ } }, "@babel/helper-remap-async-to-generator": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.0.tgz", - "integrity": "sha512-pHx7RN8X0UNHPB/fnuDnRXVZ316ZigkO8y8D835JlZ2SSdFKb6yH9MIYRU4fy/KPe5sPHDFOPvf8QLdbAGGiyw==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.4.tgz", + "integrity": "sha512-Sk4xmtVdM9sA/jCI80f+KS+Md+ZHIpjuqmYPk1M7F/upHou5e4ReYmExAiu6PVe65BhJPZA2CY9x9k4BqE5klw==", "requires": { - "@babel/helper-annotate-as-pure": "^7.7.0", - "@babel/helper-wrap-function": "^7.7.0", - "@babel/template": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/helper-annotate-as-pure": "^7.7.4", + "@babel/helper-wrap-function": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@babel/types": "^7.7.4" + }, + "dependencies": { + "@babel/generator": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.4.tgz", + "integrity": "sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg==", + "requires": { + "@babel/types": "^7.7.4", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.4.tgz", + "integrity": "sha512-2BQmQgECKzYKFPpiycoF9tlb5HA4lrVyAmLLVK177EcQAqjVLciUb2/R+n1boQ9y5ENV3uz2ZqiNw7QMBBw1Og==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/helper-function-name": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz", + "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==", + "requires": { + "@babel/helper-get-function-arity": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz", + "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz", + "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/parser": { + "version": "7.7.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.5.tgz", + "integrity": "sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig==" + }, + "@babel/template": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz", + "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/traverse": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz", + "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==", + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.7.4", + "@babel/helper-function-name": "^7.7.4", + "@babel/helper-split-export-declaration": "^7.7.4", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } + }, + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-replace-supers": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.7.0.tgz", - "integrity": "sha512-5ALYEul5V8xNdxEeWvRsBzLMxQksT7MaStpxjJf9KsnLxpAKBtfw5NeMKZJSYDa0lKdOcy0g+JT/f5mPSulUgg==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.7.4.tgz", + "integrity": "sha512-pP0tfgg9hsZWo5ZboYGuBn/bbYT/hdLPVSS4NMmiRJdwWhP0IznPwN9AE1JwyGsjSPLC364I0Qh5p+EPkGPNpg==", "requires": { - "@babel/helper-member-expression-to-functions": "^7.7.0", - "@babel/helper-optimise-call-expression": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/helper-member-expression-to-functions": "^7.7.4", + "@babel/helper-optimise-call-expression": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@babel/types": "^7.7.4" + }, + "dependencies": { + "@babel/generator": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.4.tgz", + "integrity": "sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg==", + "requires": { + "@babel/types": "^7.7.4", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + } + }, + "@babel/helper-function-name": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz", + "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==", + "requires": { + "@babel/helper-get-function-arity": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz", + "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz", + "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/parser": { + "version": "7.7.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.5.tgz", + "integrity": "sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig==" + }, + "@babel/template": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz", + "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/traverse": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz", + "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==", + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.7.4", + "@babel/helper-function-name": "^7.7.4", + "@babel/helper-split-export-declaration": "^7.7.4", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } + }, + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-simple-access": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.7.0.tgz", - "integrity": "sha512-AJ7IZD7Eem3zZRuj5JtzFAptBw7pMlS3y8Qv09vaBWoFsle0d1kAn5Wq6Q9MyBXITPOKnxwkZKoAm4bopmv26g==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.7.4.tgz", + "integrity": "sha512-zK7THeEXfan7UlWsG2A6CI/L9jVnI5+xxKZOdej39Y0YtDYKx9raHk5F2EtK9K8DHRTihYwg20ADt9S36GR78A==", "requires": { - "@babel/template": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/template": "^7.7.4", + "@babel/types": "^7.7.4" + }, + "dependencies": { + "@babel/parser": { + "version": "7.7.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.5.tgz", + "integrity": "sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig==" + }, + "@babel/template": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz", + "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helper-split-export-declaration": { @@ -245,14 +801,94 @@ } }, "@babel/helper-wrap-function": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.7.0.tgz", - "integrity": "sha512-sd4QjeMgQqzshSjecZjOp8uKfUtnpmCyQhKQrVJBBgeHAB/0FPi33h3AbVlVp07qQtMD4QgYSzaMI7VwncNK/w==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.7.4.tgz", + "integrity": "sha512-VsfzZt6wmsocOaVU0OokwrIytHND55yvyT4BPB9AIIgwr8+x7617hetdJTsuGwygN5RC6mxA9EJztTjuwm2ofg==", "requires": { - "@babel/helper-function-name": "^7.7.0", - "@babel/template": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/helper-function-name": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@babel/types": "^7.7.4" + }, + "dependencies": { + "@babel/generator": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.4.tgz", + "integrity": "sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg==", + "requires": { + "@babel/types": "^7.7.4", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + } + }, + "@babel/helper-function-name": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz", + "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==", + "requires": { + "@babel/helper-get-function-arity": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz", + "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz", + "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/parser": { + "version": "7.7.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.5.tgz", + "integrity": "sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig==" + }, + "@babel/template": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz", + "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/traverse": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz", + "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==", + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.7.4", + "@babel/helper-function-name": "^7.7.4", + "@babel/helper-split-export-declaration": "^7.7.4", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } + }, + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/helpers": { @@ -281,123 +917,176 @@ "integrity": "sha512-bqv+iCo9i+uLVbI0ILzKkvMorqxouI+GbV13ivcARXn9NNEabi2IEz912IgNpT/60BNXac5dgcfjb94NjsF33A==" }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.0.tgz", - "integrity": "sha512-ot/EZVvf3mXtZq0Pd0+tSOfGWMizqmOohXmNZg6LNFjHOV+wOPv7BvVYh8oPR8LhpIP3ye8nNooKL50YRWxpYA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.4.tgz", + "integrity": "sha512-1ypyZvGRXriY/QP668+s8sFr2mqinhkRDMPSQLNghCQE+GAkFtp+wkHVvg2+Hdki8gwP+NFzJBJ/N1BfzCCDEw==", "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.7.0", - "@babel/plugin-syntax-async-generators": "^7.2.0" + "@babel/helper-remap-async-to-generator": "^7.7.4", + "@babel/plugin-syntax-async-generators": "^7.7.4" } }, "@babel/plugin-proposal-class-properties": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.5.5.tgz", - "integrity": "sha512-AF79FsnWFxjlaosgdi421vmYG6/jg79bVD0dpD44QdgobzHKuLZ6S3vl8la9qIeSwGi8i1fS0O1mfuDAAdo1/A==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.7.4.tgz", + "integrity": "sha512-EcuXeV4Hv1X3+Q1TsuOmyyxeTRiSqurGJ26+I/FW1WbymmRRapVORm6x1Zl3iDIHyRxEs+VXWp6qnlcfcJSbbw==", "requires": { - "@babel/helper-create-class-features-plugin": "^7.5.5", + "@babel/helper-create-class-features-plugin": "^7.7.4", "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-proposal-decorators": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.6.0.tgz", - "integrity": "sha512-ZSyYw9trQI50sES6YxREXKu+4b7MAg6Qx2cvyDDYjP2Hpzd3FleOUwC9cqn1+za8d0A2ZU8SHujxFao956efUg==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.7.4.tgz", + "integrity": "sha512-GftcVDcLCwVdzKmwOBDjATd548+IE+mBo7ttgatqNDR7VG7GqIuZPtRWlMLHbhTXhcnFZiGER8iIYl1n/imtsg==", "requires": { - "@babel/helper-create-class-features-plugin": "^7.6.0", + "@babel/helper-create-class-features-plugin": "^7.7.4", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-decorators": "^7.2.0" + "@babel/plugin-syntax-decorators": "^7.7.4" } }, "@babel/plugin-proposal-dynamic-import": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.7.0.tgz", - "integrity": "sha512-7poL3Xi+QFPC7sGAzEIbXUyYzGJwbc2+gSD0AkiC5k52kH2cqHdqxm5hNFfLW3cRSTcx9bN0Fl7/6zWcLLnKAQ==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.7.4.tgz", + "integrity": "sha512-StH+nGAdO6qDB1l8sZ5UBV8AC3F2VW2I8Vfld73TMKyptMU9DY5YsJAS8U81+vEtxcH3Y/La0wG0btDrhpnhjQ==", "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-dynamic-import": "^7.2.0" + "@babel/plugin-syntax-dynamic-import": "^7.7.4" } }, "@babel/plugin-proposal-json-strings": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz", - "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.7.4.tgz", + "integrity": "sha512-wQvt3akcBTfLU/wYoqm/ws7YOAQKu8EVJEvHip/mzkNtjaclQoCCIqKXFP5/eyfnfbQCDV3OLRIK3mIVyXuZlw==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-json-strings": "^7.7.4" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.7.4.tgz", + "integrity": "sha512-TbYHmr1Gl1UC7Vo2HVuj/Naci5BEGNZ0AJhzqD2Vpr6QPFWpUmBRLrIDjedzx7/CShq0bRDS2gI4FIs77VHLVQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.7.4" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.7.4.tgz", + "integrity": "sha512-CG605v7lLpVgVldSY6kxsN9ui1DxFOyepBfuX2AzU2TNriMAYApoU55mrGw9Jr4TlrTzPCG10CL8YXyi+E/iPw==", "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-json-strings": "^7.2.0" + "@babel/plugin-syntax-numeric-separator": "^7.7.4" } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.6.2.tgz", - "integrity": "sha512-LDBXlmADCsMZV1Y9OQwMc0MyGZ8Ta/zlD9N67BfQT8uYwkRswiu2hU6nJKrjrt/58aH/vqfQlR/9yId/7A2gWw==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.7.4.tgz", + "integrity": "sha512-rnpnZR3/iWKmiQyJ3LKJpSwLDcX/nSXhdLk4Aq/tXOApIvyu7qoabrige0ylsAJffaUC51WiBu209Q0U+86OWQ==", "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.2.0" + "@babel/plugin-syntax-object-rest-spread": "^7.7.4" + }, + "dependencies": { + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.7.4.tgz", + "integrity": "sha512-mObR+r+KZq0XhRVS2BrBKBpr5jqrqzlPvS9C9vuOf5ilSwzloAl7RPWLrgKdWS6IreaVrjHxTjtyqFiOisaCwg==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + } } }, "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz", - "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.7.4.tgz", + "integrity": "sha512-DyM7U2bnsQerCQ+sejcTNZh8KQEUuC3ufzdnVnSiUv/qoGJp2Z3hanKL18KDhsBT5Wj6a7CMT5mdyCNJsEaA9w==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.7.4" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.7.4.tgz", + "integrity": "sha512-JmgaS+ygAWDR/STPe3/7y0lNlHgS+19qZ9aC06nYLwQ/XB7c0q5Xs+ksFU3EDnp9EiEsO0dnRAOKeyLHTZuW3A==", "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.2.0" + "@babel/plugin-syntax-optional-chaining": "^7.7.4" } }, "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.7.0.tgz", - "integrity": "sha512-mk34H+hp7kRBWJOOAR0ZMGCydgKMD4iN9TpDRp3IIcbunltxEY89XSimc6WbtSLCDrwcdy/EEw7h5CFCzxTchw==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.7.4.tgz", + "integrity": "sha512-cHgqHgYvffluZk85dJ02vloErm3Y6xtH+2noOBOJ2kXOJH3aVCDnj5eR/lVNlTnYu4hndAPJD3rTFjW3qee0PA==", "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.7.0", + "@babel/helper-create-regexp-features-plugin": "^7.7.4", "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-syntax-async-generators": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz", - "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.7.4.tgz", + "integrity": "sha512-Li4+EjSpBgxcsmeEF8IFcfV/+yJGxHXDirDkEoyFjumuwbmfCVHUt0HuowD/iGM7OhIRyXJH9YXxqiH6N815+g==", "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-syntax-decorators": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.2.0.tgz", - "integrity": "sha512-38QdqVoXdHUQfTpZo3rQwqQdWtCn5tMv4uV6r2RMfTqNBuv4ZBhz79SfaQWKTVmxHjeFv/DnXVC/+agHCklYWA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.7.4.tgz", + "integrity": "sha512-0oNLWNH4k5ZbBVfAwiTU53rKFWIeTh6ZlaWOXWJc4ywxs0tjz5fc3uZ6jKAnZSxN98eXVgg7bJIuzjX+3SXY+A==", "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-syntax-dynamic-import": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz", - "integrity": "sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.7.4.tgz", + "integrity": "sha512-jHQW0vbRGvwQNgyVxwDh4yuXu4bH1f5/EICJLAhl1SblLs2CDhrsmCk+v5XLdE9wxtAFRyxx+P//Iw+a5L/tTg==", "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-syntax-flow": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.7.0.tgz", - "integrity": "sha512-vQMV07p+L+jZeUnvX3pEJ9EiXGCjB5CTTvsirFD9rpEuATnoAvLBLoYbw1v5tyn3d2XxSuvEKi8cV3KqYUa0vQ==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.7.4.tgz", + "integrity": "sha512-2AMAWl5PsmM5KPkB22cvOkUyWk6MjUaqhHNU5nSPUl/ns3j5qLfw2SuYP5RbVZ0tfLvePr4zUScbICtDP2CUNw==", "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-syntax-json-strings": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz", - "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.7.4.tgz", + "integrity": "sha512-QpGupahTQW1mHRXddMG5srgpHWqRLwJnJZKXTigB9RPFCCGbDGCgBeM/iC82ICXp414WeYx/tD54w7M2qRqTMg==", "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-syntax-jsx": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.2.0.tgz", - "integrity": "sha512-VyN4QANJkRW6lDBmENzRszvZf3/4AXaj9YR7GwrWeeN9tEBPuXbmDYVU9bYBN0D70zCWVwUy0HWq2553VCb6Hw==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.7.4.tgz", + "integrity": "sha512-wuy6fiMe9y7HeZBWXYCGt2RGxZOj0BImZ9EyXJVnVGBKO/Br592rbR3rtIQn0eQhAk9vqaKP5n8tVqEFBQMfLg==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.7.4.tgz", + "integrity": "sha512-XKh/yIRPiQTOeBg0QJjEus5qiSKucKAiApNtO1psqG7D17xmE+X2i5ZqBEuSvo0HRuyPaKaSN/Gy+Ha9KFQolw==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.7.4.tgz", + "integrity": "sha512-vmlUUBlLuFnbpaR+1kKIdo62xQEN+THWbtAHSEilo+0rHl2dKKCn6GLUVKpI848wL/T0ZPQgAy8asRJ9yYEjog==", "requires": { "@babel/helper-plugin-utils": "^7.0.0" } @@ -411,318 +1100,510 @@ } }, "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz", - "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.7.4.tgz", + "integrity": "sha512-4ZSuzWgFxqHRE31Glu+fEr/MirNZOMYmD/0BhBWyLyOOQz/gTAl7QmWm2hX1QxEIXsr2vkdlwxIzTyiYRC4xcQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.7.4.tgz", + "integrity": "sha512-2MqYD5WjZSbJdUagnJvIdSfkb/ucOC9/1fRJxm7GAxY6YQLWlUvkfxoNbUPcPLHJyetKUDQ4+yyuUyAoc0HriA==", "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-syntax-top-level-await": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.7.0.tgz", - "integrity": "sha512-hi8FUNiFIY1fnUI2n1ViB1DR0R4QeK4iHcTlW6aJkrPoTdb8Rf1EMQ6GT3f67DDkYyWgew9DFoOZ6gOoEsdzTA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.7.4.tgz", + "integrity": "sha512-wdsOw0MvkL1UIgiQ/IFr3ETcfv1xb8RMM0H9wbiDyLaJFyiDg5oZvDLCXosIXmFeIlweML5iOBXAkqddkYNizg==", "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-syntax-typescript": { - "version": "7.3.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.3.3.tgz", - "integrity": "sha512-dGwbSMA1YhVS8+31CnPR7LB4pcbrzcV99wQzby4uAfrkZPYZlQ7ImwdpzLqi6Z6IL02b8IAL379CaMwo0x5Lag==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.7.4.tgz", + "integrity": "sha512-77blgY18Hud4NM1ggTA8xVT/dBENQf17OpiToSa2jSmEY3fWXD2jwrdVlO4kq5yzUTeF15WSQ6b4fByNvJcjpQ==", "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-arrow-functions": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", - "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.7.4.tgz", + "integrity": "sha512-zUXy3e8jBNPiffmqkHRNDdZM2r8DWhCB7HhcoyZjiK1TxYEluLHAvQuYnTT+ARqRpabWqy/NHkO6e3MsYB5YfA==", "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.7.0.tgz", - "integrity": "sha512-vLI2EFLVvRBL3d8roAMqtVY0Bm9C1QzLkdS57hiKrjUBSqsQYrBsMCeOg/0KK7B0eK9V71J5mWcha9yyoI2tZw==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.7.4.tgz", + "integrity": "sha512-zpUTZphp5nHokuy8yLlyafxCJ0rSlFoSHypTUWgpdwoDXWQcseaect7cJ8Ppk6nunOM6+5rPMkod4OYKPR5MUg==", "requires": { - "@babel/helper-module-imports": "^7.7.0", + "@babel/helper-module-imports": "^7.7.4", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.7.0" + "@babel/helper-remap-async-to-generator": "^7.7.4" + }, + "dependencies": { + "@babel/helper-module-imports": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.7.4.tgz", + "integrity": "sha512-dGcrX6K9l8258WFjyDLJwuVKxR4XZfU0/vTUgOQYWEnRD8mgr+p4d6fCUMq/ys0h4CCt/S5JhbvtyErjWouAUQ==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/plugin-transform-block-scoped-functions": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz", - "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.7.4.tgz", + "integrity": "sha512-kqtQzwtKcpPclHYjLK//3lH8OFsCDuDJBaFhVwf8kqdnF6MN4l618UDlcA7TfRs3FayrHj+svYnSX8MC9zmUyQ==", "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-block-scoping": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.3.tgz", - "integrity": "sha512-7hvrg75dubcO3ZI2rjYTzUrEuh1E9IyDEhhB6qfcooxhDA33xx2MasuLVgdxzcP6R/lipAC6n9ub9maNW6RKdw==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.7.4.tgz", + "integrity": "sha512-2VBe9u0G+fDt9B5OV5DQH4KBf5DoiNkwFKOz0TCvBWvdAN2rOykCTkrL+jTLxfCAm76l9Qo5OqL7HBOx2dWggg==", "requires": { "@babel/helper-plugin-utils": "^7.0.0", "lodash": "^4.17.13" } }, "@babel/plugin-transform-classes": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.7.0.tgz", - "integrity": "sha512-/b3cKIZwGeUesZheU9jNYcwrEA7f/Bo4IdPmvp7oHgvks2majB5BoT5byAql44fiNQYOPzhk2w8DbgfuafkMoA==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.7.0", - "@babel/helper-define-map": "^7.7.0", - "@babel/helper-function-name": "^7.7.0", - "@babel/helper-optimise-call-expression": "^7.7.0", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.7.4.tgz", + "integrity": "sha512-sK1mjWat7K+buWRuImEzjNf68qrKcrddtpQo3swi9j7dUcG6y6R6+Di039QN2bD1dykeswlagupEmpOatFHHUg==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.7.4", + "@babel/helper-define-map": "^7.7.4", + "@babel/helper-function-name": "^7.7.4", + "@babel/helper-optimise-call-expression": "^7.7.4", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.7.0", - "@babel/helper-split-export-declaration": "^7.7.0", + "@babel/helper-replace-supers": "^7.7.4", + "@babel/helper-split-export-declaration": "^7.7.4", "globals": "^11.1.0" + }, + "dependencies": { + "@babel/helper-annotate-as-pure": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.4.tgz", + "integrity": "sha512-2BQmQgECKzYKFPpiycoF9tlb5HA4lrVyAmLLVK177EcQAqjVLciUb2/R+n1boQ9y5ENV3uz2ZqiNw7QMBBw1Og==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/helper-function-name": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz", + "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==", + "requires": { + "@babel/helper-get-function-arity": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz", + "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz", + "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/parser": { + "version": "7.7.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.5.tgz", + "integrity": "sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig==" + }, + "@babel/template": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz", + "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/plugin-transform-computed-properties": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz", - "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.7.4.tgz", + "integrity": "sha512-bSNsOsZnlpLLyQew35rl4Fma3yKWqK3ImWMSC/Nc+6nGjC9s5NFWAer1YQ899/6s9HxO2zQC1WoFNfkOqRkqRQ==", "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-destructuring": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.6.0.tgz", - "integrity": "sha512-2bGIS5P1v4+sWTCnKNDZDxbGvEqi0ijeqM/YqHtVGrvG2y0ySgnEEhXErvE9dA0bnIzY9bIzdFK0jFA46ASIIQ==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.7.4.tgz", + "integrity": "sha512-4jFMXI1Cu2aXbcXXl8Lr6YubCn6Oc7k9lLsu8v61TZh+1jny2BWmdtvY9zSUlLdGUvcy9DMAWyZEOqjsbeg/wA==", "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-dotall-regex": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.7.0.tgz", - "integrity": "sha512-3QQlF7hSBnSuM1hQ0pS3pmAbWLax/uGNCbPBND9y+oJ4Y776jsyujG2k0Sn2Aj2a0QwVOiOFL5QVPA7spjvzSA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.7.4.tgz", + "integrity": "sha512-mk0cH1zyMa/XHeb6LOTXTbG7uIJ8Rrjlzu91pUx/KS3JpcgaTDwMS8kM+ar8SLOvlL2Lofi4CGBAjCo3a2x+lw==", "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.7.0", + "@babel/helper-create-regexp-features-plugin": "^7.7.4", "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-duplicate-keys": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz", - "integrity": "sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.7.4.tgz", + "integrity": "sha512-g1y4/G6xGWMD85Tlft5XedGaZBCIVN+/P0bs6eabmcPP9egFleMAo65OOjlhcz1njpwagyY3t0nsQC9oTFegJA==", "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-exponentiation-operator": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz", - "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.7.4.tgz", + "integrity": "sha512-MCqiLfCKm6KEA1dglf6Uqq1ElDIZwFuzz1WH5mTf8k2uQSxEJMbOIEh7IZv7uichr7PMfi5YVSrr1vz+ipp7AQ==", "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.7.4", "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-flow-strip-types": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.4.4.tgz", - "integrity": "sha512-WyVedfeEIILYEaWGAUWzVNyqG4sfsNooMhXWsu/YzOvVGcsnPb5PguysjJqI3t3qiaYj0BR8T2f5njdjTGe44Q==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.7.4.tgz", + "integrity": "sha512-w9dRNlHY5ElNimyMYy0oQowvQpwt/PRHI0QS98ZJCTZU2bvSnKXo5zEiD5u76FBPigTm8TkqzmnUTg16T7qbkA==", "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-flow": "^7.2.0" + "@babel/plugin-syntax-flow": "^7.7.4" } }, "@babel/plugin-transform-for-of": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz", - "integrity": "sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.7.4.tgz", + "integrity": "sha512-zZ1fD1B8keYtEcKF+M1TROfeHTKnijcVQm0yO/Yu1f7qoDoxEIc/+GX6Go430Bg84eM/xwPFp0+h4EbZg7epAA==", "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-function-name": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.7.0.tgz", - "integrity": "sha512-P5HKu0d9+CzZxP5jcrWdpe7ZlFDe24bmqP6a6X8BHEBl/eizAsY8K6LX8LASZL0Jxdjm5eEfzp+FIrxCm/p8bA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.7.4.tgz", + "integrity": "sha512-E/x09TvjHNhsULs2IusN+aJNRV5zKwxu1cpirZyRPw+FyyIKEHPXTsadj48bVpc1R5Qq1B5ZkzumuFLytnbT6g==", "requires": { - "@babel/helper-function-name": "^7.7.0", + "@babel/helper-function-name": "^7.7.4", "@babel/helper-plugin-utils": "^7.0.0" + }, + "dependencies": { + "@babel/helper-function-name": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz", + "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==", + "requires": { + "@babel/helper-get-function-arity": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz", + "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/parser": { + "version": "7.7.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.5.tgz", + "integrity": "sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig==" + }, + "@babel/template": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz", + "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/plugin-transform-literals": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz", - "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.7.4.tgz", + "integrity": "sha512-X2MSV7LfJFm4aZfxd0yLVFrEXAgPqYoDG53Br/tCKiKYfX0MjVjQeWPIhPHHsCqzwQANq+FLN786fF5rgLS+gw==", "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-member-expression-literals": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz", - "integrity": "sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.7.4.tgz", + "integrity": "sha512-9VMwMO7i69LHTesL0RdGy93JU6a+qOPuvB4F4d0kR0zyVjJRVJRaoaGjhtki6SzQUu8yen/vxPKN6CWnCUw6bA==", "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-modules-amd": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz", - "integrity": "sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg==", + "version": "7.7.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.7.5.tgz", + "integrity": "sha512-CT57FG4A2ZUNU1v+HdvDSDrjNWBrtCmSH6YbbgN3Lrf0Di/q/lWRxZrE72p3+HCCz9UjfZOEBdphgC0nzOS6DQ==", "requires": { - "@babel/helper-module-transforms": "^7.1.0", + "@babel/helper-module-transforms": "^7.7.5", "@babel/helper-plugin-utils": "^7.0.0", "babel-plugin-dynamic-import-node": "^2.3.0" } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.7.0.tgz", - "integrity": "sha512-KEMyWNNWnjOom8vR/1+d+Ocz/mILZG/eyHHO06OuBQ2aNhxT62fr4y6fGOplRx+CxCSp3IFwesL8WdINfY/3kg==", + "version": "7.7.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.7.5.tgz", + "integrity": "sha512-9Cq4zTFExwFhQI6MT1aFxgqhIsMWQWDVwOgLzl7PTWJHsNaqFvklAU+Oz6AQLAS0dJKTwZSOCo20INwktxpi3Q==", "requires": { - "@babel/helper-module-transforms": "^7.7.0", + "@babel/helper-module-transforms": "^7.7.5", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-simple-access": "^7.7.0", + "@babel/helper-simple-access": "^7.7.4", "babel-plugin-dynamic-import-node": "^2.3.0" } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.7.0.tgz", - "integrity": "sha512-ZAuFgYjJzDNv77AjXRqzQGlQl4HdUM6j296ee4fwKVZfhDR9LAGxfvXjBkb06gNETPnN0sLqRm9Gxg4wZH6dXg==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.7.4.tgz", + "integrity": "sha512-y2c96hmcsUi6LrMqvmNDPBBiGCiQu0aYqpHatVVu6kD4mFEXKjyNxd/drc18XXAf9dv7UXjrZwBVmTTGaGP8iw==", "requires": { - "@babel/helper-hoist-variables": "^7.7.0", + "@babel/helper-hoist-variables": "^7.7.4", "@babel/helper-plugin-utils": "^7.0.0", "babel-plugin-dynamic-import-node": "^2.3.0" } }, "@babel/plugin-transform-modules-umd": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.7.0.tgz", - "integrity": "sha512-u7eBA03zmUswQ9LQ7Qw0/ieC1pcAkbp5OQatbWUzY1PaBccvuJXUkYzoN1g7cqp7dbTu6Dp9bXyalBvD04AANA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.7.4.tgz", + "integrity": "sha512-u2B8TIi0qZI4j8q4C51ktfO7E3cQ0qnaXFI1/OXITordD40tt17g/sXqgNNCcMTcBFKrUPcGDx+TBJuZxLx7tw==", "requires": { - "@babel/helper-module-transforms": "^7.7.0", + "@babel/helper-module-transforms": "^7.7.4", "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.7.0.tgz", - "integrity": "sha512-+SicSJoKouPctL+j1pqktRVCgy+xAch1hWWTMy13j0IflnyNjaoskj+DwRQFimHbLqO3sq2oN2CXMvXq3Bgapg==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.7.4.tgz", + "integrity": "sha512-jBUkiqLKvUWpv9GLSuHUFYdmHg0ujC1JEYoZUfeOOfNydZXp1sXObgyPatpcwjWgsdBGsagWW0cdJpX/DO2jMw==", "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.7.0" + "@babel/helper-create-regexp-features-plugin": "^7.7.4" } }, "@babel/plugin-transform-new-target": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz", - "integrity": "sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.7.4.tgz", + "integrity": "sha512-CnPRiNtOG1vRodnsyGX37bHQleHE14B9dnnlgSeEs3ek3fHN1A1SScglTCg1sfbe7sRQ2BUcpgpTpWSfMKz3gg==", "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-object-super": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz", - "integrity": "sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.7.4.tgz", + "integrity": "sha512-ho+dAEhC2aRnff2JCA0SAK7V2R62zJd/7dmtoe7MHcso4C2mS+vZjn1Pb1pCVZvJs1mgsvv5+7sT+m3Bysb6eg==", "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.5.5" + "@babel/helper-replace-supers": "^7.7.4" } }, "@babel/plugin-transform-parameters": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz", - "integrity": "sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.7.4.tgz", + "integrity": "sha512-VJwhVePWPa0DqE9vcfptaJSzNDKrWU/4FbYCjZERtmqEs05g3UMXnYMZoXja7JAJ7Y7sPZipwm/pGApZt7wHlw==", "requires": { - "@babel/helper-call-delegate": "^7.4.4", - "@babel/helper-get-function-arity": "^7.0.0", + "@babel/helper-call-delegate": "^7.7.4", + "@babel/helper-get-function-arity": "^7.7.4", "@babel/helper-plugin-utils": "^7.0.0" + }, + "dependencies": { + "@babel/helper-get-function-arity": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz", + "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/plugin-transform-property-literals": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz", - "integrity": "sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.7.4.tgz", + "integrity": "sha512-MatJhlC4iHsIskWYyawl53KuHrt+kALSADLQQ/HkhTjX954fkxIEh4q5slL4oRAnsm/eDoZ4q0CIZpcqBuxhJQ==", "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-react-constant-elements": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.6.3.tgz", - "integrity": "sha512-1/YogSSU7Tby9rq2VCmhuRg+6pxsHy2rI7w/oo8RKoBt6uBUFG+mk6x13kK+FY1/ggN92HAfg7ADd1v1+NCOKg==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.7.4.tgz", + "integrity": "sha512-U6XkHZ8RnmeEb8jBUOpeo6oFka5RhLgxAVvK4/fBbwoYlsHQYLb8I37ymTPDVsrWjqb94+hueuWQA/1OAA4rAQ==", "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-annotate-as-pure": "^7.7.4", "@babel/helper-plugin-utils": "^7.0.0" + }, + "dependencies": { + "@babel/helper-annotate-as-pure": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.4.tgz", + "integrity": "sha512-2BQmQgECKzYKFPpiycoF9tlb5HA4lrVyAmLLVK177EcQAqjVLciUb2/R+n1boQ9y5ENV3uz2ZqiNw7QMBBw1Og==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/plugin-transform-react-display-name": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.2.0.tgz", - "integrity": "sha512-Htf/tPa5haZvRMiNSQSFifK12gtr/8vwfr+A9y69uF0QcU77AVu4K7MiHEkTxF7lQoHOL0F9ErqgfNEAKgXj7A==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.7.4.tgz", + "integrity": "sha512-sBbIvqYkthai0X0vkD2xsAwluBp+LtNHH+/V4a5ydifmTtb8KOVOlrMIk/MYmIc4uTYDnjZUHQildYNo36SRJw==", "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-react-jsx": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.7.0.tgz", - "integrity": "sha512-mXhBtyVB1Ujfy+0L6934jeJcSXj/VCg6whZzEcgiiZHNS0PGC7vUCsZDQCxxztkpIdF+dY1fUMcjAgEOC3ZOMQ==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.7.4.tgz", + "integrity": "sha512-LixU4BS95ZTEAZdPaIuyg/k8FiiqN9laQ0dMHB4MlpydHY53uQdWCUrwjLr5o6ilS6fAgZey4Q14XBjl5tL6xw==", "requires": { - "@babel/helper-builder-react-jsx": "^7.7.0", + "@babel/helper-builder-react-jsx": "^7.7.4", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-jsx": "^7.2.0" + "@babel/plugin-syntax-jsx": "^7.7.4" } }, "@babel/plugin-transform-react-jsx-self": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.2.0.tgz", - "integrity": "sha512-v6S5L/myicZEy+jr6ielB0OR8h+EH/1QFx/YJ7c7Ua+7lqsjj/vW6fD5FR9hB/6y7mGbfT4vAURn3xqBxsUcdg==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.7.4.tgz", + "integrity": "sha512-PWYjSfqrO273mc1pKCRTIJXyqfc9vWYBax88yIhQb+bpw3XChVC7VWS4VwRVs63wFHKxizvGSd00XEr+YB9Q2A==", "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-jsx": "^7.2.0" + "@babel/plugin-syntax-jsx": "^7.7.4" } }, "@babel/plugin-transform-react-jsx-source": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.5.0.tgz", - "integrity": "sha512-58Q+Jsy4IDCZx7kqEZuSDdam/1oW8OdDX8f+Loo6xyxdfg1yF0GE2XNJQSTZCaMol93+FBzpWiPEwtbMloAcPg==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.7.4.tgz", + "integrity": "sha512-5ZU9FnPhqtHsOXxutRtXZAzoEJwDaP32QcobbMP1/qt7NYcsCNK8XgzJcJfoEr/ZnzVvUNInNjIW22Z6I8p9mg==", "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-jsx": "^7.2.0" + "@babel/plugin-syntax-jsx": "^7.7.4" } }, "@babel/plugin-transform-regenerator": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.7.0.tgz", - "integrity": "sha512-AXmvnC+0wuj/cFkkS/HFHIojxH3ffSXE+ttulrqWjZZRaUOonfJc60e1wSNT4rV8tIunvu/R3wCp71/tLAa9xg==", + "version": "7.7.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.7.5.tgz", + "integrity": "sha512-/8I8tPvX2FkuEyWbjRCt4qTAgZK0DVy8QRguhA524UH48RfGJy94On2ri+dCuwOpcerPRl9O4ebQkRcVzIaGBw==", "requires": { "regenerator-transform": "^0.14.0" } }, "@babel/plugin-transform-reserved-words": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz", - "integrity": "sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.7.4.tgz", + "integrity": "sha512-OrPiUB5s5XvkCO1lS7D8ZtHcswIC57j62acAnJZKqGGnHP+TIc/ljQSrgdX/QyOTdEK5COAhuc820Hi1q2UgLQ==", "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-runtime": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.6.0.tgz", - "integrity": "sha512-Da8tMf7uClzwUm/pnJ1S93m/aRXmoYNDD7TkHua8xBDdaAs54uZpTWvEt6NGwmoVMb9mZbntfTqmG2oSzN/7Vg==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.7.4.tgz", + "integrity": "sha512-O8kSkS5fP74Ad/8pfsCMGa8sBRdLxYoSReaARRNSz3FbFQj3z/QUvoUmJ28gn9BO93YfnXc3j+Xyaqe8cKDNBQ==", "requires": { - "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-module-imports": "^7.7.4", "@babel/helper-plugin-utils": "^7.0.0", "resolve": "^1.8.1", "semver": "^5.5.1" }, "dependencies": { + "@babel/helper-module-imports": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.7.4.tgz", + "integrity": "sha512-dGcrX6K9l8258WFjyDLJwuVKxR4XZfU0/vTUgOQYWEnRD8mgr+p4d6fCUMq/ys0h4CCt/S5JhbvtyErjWouAUQ==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -731,124 +1612,170 @@ } }, "@babel/plugin-transform-shorthand-properties": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz", - "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.7.4.tgz", + "integrity": "sha512-q+suddWRfIcnyG5YiDP58sT65AJDZSUhXQDZE3r04AuqD6d/XLaQPPXSBzP2zGerkgBivqtQm9XKGLuHqBID6Q==", "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-spread": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.6.2.tgz", - "integrity": "sha512-DpSvPFryKdK1x+EDJYCy28nmAaIMdxmhot62jAXF/o99iA33Zj2Lmcp3vDmz+MUh0LNYVPvfj5iC3feb3/+PFg==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.7.4.tgz", + "integrity": "sha512-8OSs0FLe5/80cndziPlg4R0K6HcWSM0zyNhHhLsmw/Nc5MaA49cAsnoJ/t/YZf8qkG7fD+UjTRaApVDB526d7Q==", "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-sticky-regex": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz", - "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.7.4.tgz", + "integrity": "sha512-Ls2NASyL6qtVe1H1hXts9yuEeONV2TJZmplLONkMPUG158CtmnrzW5Q5teibM5UVOFjG0D3IC5mzXR6pPpUY7A==", "requires": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/helper-regex": "^7.0.0" } }, "@babel/plugin-transform-template-literals": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz", - "integrity": "sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.7.4.tgz", + "integrity": "sha512-sA+KxLwF3QwGj5abMHkHgshp9+rRz+oY9uoRil4CyLtgEuE/88dpkeWgNk5qKVsJE9iSfly3nvHapdRiIS2wnQ==", "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-annotate-as-pure": "^7.7.4", "@babel/helper-plugin-utils": "^7.0.0" + }, + "dependencies": { + "@babel/helper-annotate-as-pure": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.4.tgz", + "integrity": "sha512-2BQmQgECKzYKFPpiycoF9tlb5HA4lrVyAmLLVK177EcQAqjVLciUb2/R+n1boQ9y5ENV3uz2ZqiNw7QMBBw1Og==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/plugin-transform-typeof-symbol": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz", - "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.7.4.tgz", + "integrity": "sha512-KQPUQ/7mqe2m0B8VecdyaW5XcQYaePyl9R7IsKd+irzj6jvbhoGnRE+M0aNkyAzI07VfUQ9266L5xMARitV3wg==", "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/plugin-transform-typescript": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.7.2.tgz", - "integrity": "sha512-UWhDaJRqdPUtdK1s0sKYdoRuqK0NepjZto2UZltvuCgMoMZmdjhgz5hcRokie/3aYEaSz3xvusyoayVaq4PjRg==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.7.4.tgz", + "integrity": "sha512-X8e3tcPEKnwwPVG+vP/vSqEShkwODOEeyQGod82qrIuidwIrfnsGn11qPM1jBLF4MqguTXXYzm58d0dY+/wdpg==", "requires": { - "@babel/helper-create-class-features-plugin": "^7.7.0", + "@babel/helper-create-class-features-plugin": "^7.7.4", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-typescript": "^7.2.0" + "@babel/plugin-syntax-typescript": "^7.7.4" } }, "@babel/plugin-transform-unicode-regex": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.7.0.tgz", - "integrity": "sha512-RrThb0gdrNwFAqEAAx9OWgtx6ICK69x7i9tCnMdVrxQwSDp/Abu9DXFU5Hh16VP33Rmxh04+NGW28NsIkFvFKA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.7.4.tgz", + "integrity": "sha512-N77UUIV+WCvE+5yHw+oks3m18/umd7y392Zv7mYTpFqHtkpcc+QUz+gLJNTWVlWROIWeLqY0f3OjZxV5TcXnRw==", "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.7.0", + "@babel/helper-create-regexp-features-plugin": "^7.7.4", "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/preset-env": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.7.1.tgz", - "integrity": "sha512-/93SWhi3PxcVTDpSqC+Dp4YxUu3qZ4m7I76k0w73wYfn7bGVuRIO4QUz95aJksbS+AD1/mT1Ie7rbkT0wSplaA==", + "version": "7.7.6", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.7.6.tgz", + "integrity": "sha512-k5hO17iF/Q7tR9Jv8PdNBZWYW6RofxhnxKjBMc0nG4JTaWvOTiPoO/RLFwAKcA4FpmuBFm6jkoqaRJLGi0zdaQ==", "requires": { - "@babel/helper-module-imports": "^7.7.0", + "@babel/helper-module-imports": "^7.7.4", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-async-generator-functions": "^7.7.0", - "@babel/plugin-proposal-dynamic-import": "^7.7.0", - "@babel/plugin-proposal-json-strings": "^7.2.0", - "@babel/plugin-proposal-object-rest-spread": "^7.6.2", - "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.7.0", - "@babel/plugin-syntax-async-generators": "^7.2.0", - "@babel/plugin-syntax-dynamic-import": "^7.2.0", - "@babel/plugin-syntax-json-strings": "^7.2.0", - "@babel/plugin-syntax-object-rest-spread": "^7.2.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", - "@babel/plugin-syntax-top-level-await": "^7.7.0", - "@babel/plugin-transform-arrow-functions": "^7.2.0", - "@babel/plugin-transform-async-to-generator": "^7.7.0", - "@babel/plugin-transform-block-scoped-functions": "^7.2.0", - "@babel/plugin-transform-block-scoping": "^7.6.3", - "@babel/plugin-transform-classes": "^7.7.0", - "@babel/plugin-transform-computed-properties": "^7.2.0", - "@babel/plugin-transform-destructuring": "^7.6.0", - "@babel/plugin-transform-dotall-regex": "^7.7.0", - "@babel/plugin-transform-duplicate-keys": "^7.5.0", - "@babel/plugin-transform-exponentiation-operator": "^7.2.0", - "@babel/plugin-transform-for-of": "^7.4.4", - "@babel/plugin-transform-function-name": "^7.7.0", - "@babel/plugin-transform-literals": "^7.2.0", - "@babel/plugin-transform-member-expression-literals": "^7.2.0", - "@babel/plugin-transform-modules-amd": "^7.5.0", - "@babel/plugin-transform-modules-commonjs": "^7.7.0", - "@babel/plugin-transform-modules-systemjs": "^7.7.0", - "@babel/plugin-transform-modules-umd": "^7.7.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.7.0", - "@babel/plugin-transform-new-target": "^7.4.4", - "@babel/plugin-transform-object-super": "^7.5.5", - "@babel/plugin-transform-parameters": "^7.4.4", - "@babel/plugin-transform-property-literals": "^7.2.0", - "@babel/plugin-transform-regenerator": "^7.7.0", - "@babel/plugin-transform-reserved-words": "^7.2.0", - "@babel/plugin-transform-shorthand-properties": "^7.2.0", - "@babel/plugin-transform-spread": "^7.6.2", - "@babel/plugin-transform-sticky-regex": "^7.2.0", - "@babel/plugin-transform-template-literals": "^7.4.4", - "@babel/plugin-transform-typeof-symbol": "^7.2.0", - "@babel/plugin-transform-unicode-regex": "^7.7.0", - "@babel/types": "^7.7.1", + "@babel/plugin-proposal-async-generator-functions": "^7.7.4", + "@babel/plugin-proposal-dynamic-import": "^7.7.4", + "@babel/plugin-proposal-json-strings": "^7.7.4", + "@babel/plugin-proposal-object-rest-spread": "^7.7.4", + "@babel/plugin-proposal-optional-catch-binding": "^7.7.4", + "@babel/plugin-proposal-unicode-property-regex": "^7.7.4", + "@babel/plugin-syntax-async-generators": "^7.7.4", + "@babel/plugin-syntax-dynamic-import": "^7.7.4", + "@babel/plugin-syntax-json-strings": "^7.7.4", + "@babel/plugin-syntax-object-rest-spread": "^7.7.4", + "@babel/plugin-syntax-optional-catch-binding": "^7.7.4", + "@babel/plugin-syntax-top-level-await": "^7.7.4", + "@babel/plugin-transform-arrow-functions": "^7.7.4", + "@babel/plugin-transform-async-to-generator": "^7.7.4", + "@babel/plugin-transform-block-scoped-functions": "^7.7.4", + "@babel/plugin-transform-block-scoping": "^7.7.4", + "@babel/plugin-transform-classes": "^7.7.4", + "@babel/plugin-transform-computed-properties": "^7.7.4", + "@babel/plugin-transform-destructuring": "^7.7.4", + "@babel/plugin-transform-dotall-regex": "^7.7.4", + "@babel/plugin-transform-duplicate-keys": "^7.7.4", + "@babel/plugin-transform-exponentiation-operator": "^7.7.4", + "@babel/plugin-transform-for-of": "^7.7.4", + "@babel/plugin-transform-function-name": "^7.7.4", + "@babel/plugin-transform-literals": "^7.7.4", + "@babel/plugin-transform-member-expression-literals": "^7.7.4", + "@babel/plugin-transform-modules-amd": "^7.7.5", + "@babel/plugin-transform-modules-commonjs": "^7.7.5", + "@babel/plugin-transform-modules-systemjs": "^7.7.4", + "@babel/plugin-transform-modules-umd": "^7.7.4", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.7.4", + "@babel/plugin-transform-new-target": "^7.7.4", + "@babel/plugin-transform-object-super": "^7.7.4", + "@babel/plugin-transform-parameters": "^7.7.4", + "@babel/plugin-transform-property-literals": "^7.7.4", + "@babel/plugin-transform-regenerator": "^7.7.5", + "@babel/plugin-transform-reserved-words": "^7.7.4", + "@babel/plugin-transform-shorthand-properties": "^7.7.4", + "@babel/plugin-transform-spread": "^7.7.4", + "@babel/plugin-transform-sticky-regex": "^7.7.4", + "@babel/plugin-transform-template-literals": "^7.7.4", + "@babel/plugin-transform-typeof-symbol": "^7.7.4", + "@babel/plugin-transform-unicode-regex": "^7.7.4", + "@babel/types": "^7.7.4", "browserslist": "^4.6.0", - "core-js-compat": "^3.1.1", + "core-js-compat": "^3.4.7", "invariant": "^2.2.2", "js-levenshtein": "^1.1.3", "semver": "^5.5.0" }, "dependencies": { + "@babel/helper-module-imports": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.7.4.tgz", + "integrity": "sha512-dGcrX6K9l8258WFjyDLJwuVKxR4XZfU0/vTUgOQYWEnRD8mgr+p4d6fCUMq/ys0h4CCt/S5JhbvtyErjWouAUQ==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.7.4.tgz", + "integrity": "sha512-mObR+r+KZq0XhRVS2BrBKBpr5jqrqzlPvS9C9vuOf5ilSwzloAl7RPWLrgKdWS6IreaVrjHxTjtyqFiOisaCwg==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -857,24 +1784,24 @@ } }, "@babel/preset-react": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.7.0.tgz", - "integrity": "sha512-IXXgSUYBPHUGhUkH+89TR6faMcBtuMW0h5OHbMuVbL3/5wK2g6a2M2BBpkLa+Kw0sAHiZ9dNVgqJMDP/O4GRBA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.7.4.tgz", + "integrity": "sha512-j+vZtg0/8pQr1H8wKoaJyGL2IEk3rG/GIvua7Sec7meXVIvGycihlGMx5xcU00kqCJbwzHs18xTu3YfREOqQ+g==", "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-transform-react-display-name": "^7.0.0", - "@babel/plugin-transform-react-jsx": "^7.7.0", - "@babel/plugin-transform-react-jsx-self": "^7.0.0", - "@babel/plugin-transform-react-jsx-source": "^7.0.0" + "@babel/plugin-transform-react-display-name": "^7.7.4", + "@babel/plugin-transform-react-jsx": "^7.7.4", + "@babel/plugin-transform-react-jsx-self": "^7.7.4", + "@babel/plugin-transform-react-jsx-source": "^7.7.4" } }, "@babel/preset-typescript": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.6.0.tgz", - "integrity": "sha512-4xKw3tTcCm0qApyT6PqM9qniseCE79xGHiUnNdKGdxNsGUc2X7WwZybqIpnTmoukg3nhPceI5KPNzNqLNeIJww==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.7.4.tgz", + "integrity": "sha512-rqrjxfdiHPsnuPur0jKrIIGQCIgoTWMTjlbWE69G4QJ6TIOVnnRnIJhUxNTL/VwDmEAVX08Tq3B1nirer5341w==", "requires": { "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-transform-typescript": "^7.6.0" + "@babel/plugin-transform-typescript": "^7.7.4" } }, "@babel/runtime": { @@ -885,6 +1812,15 @@ "regenerator-runtime": "^0.13.2" } }, + "@babel/runtime-corejs3": { + "version": "7.7.6", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.7.6.tgz", + "integrity": "sha512-NrRUehqG0sMSCaP+0XV/vOvvjNl4BQOWq3Qys1Q2KTEm5tGMo9h0dHnIzeKerj0a7SIB8LP5kYg/T1raE3FoKQ==", + "requires": { + "core-js-pure": "^3.0.0", + "regenerator-runtime": "^0.13.2" + } + }, "@babel/template": { "version": "7.7.0", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.0.tgz", @@ -936,9 +1872,9 @@ "integrity": "sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==" }, "@csstools/normalize.css": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-9.0.1.tgz", - "integrity": "sha512-6It2EVfGskxZCQhuykrfnALg7oVeiI6KclWSmGDqB0AiInVrTGB9Jp9i4/Ad21u9Jde/voVQz6eFX/eSg/UsPA==" + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-10.1.0.tgz", + "integrity": "sha512-ij4wRiunFfaJxjB0BdrYHIH8FxBJpOwNPhhAcunlmPdXudL1WQV1qoP9un6JsEBAgQH+7UXyyjh0g7jTxXK6tg==" }, "@emotion/is-prop-valid": { "version": "0.8.5", @@ -959,9 +1895,9 @@ "integrity": "sha512-kBa+cDHOR9jpRJ+kcGMsysrls0leukrm68DmFQoMIWQcXdr2cZvyvypWuGYT7U+9kAExUE7+T7r6G3C3A6L8MQ==" }, "@hapi/address": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.2.tgz", - "integrity": "sha512-O4QDrx+JoGKZc6aN64L04vqa7e41tIiLU+OvKdcYaEMP97UttL0f9GIi9/0A4WAMx0uBd6SidDIhktZhgOcN8Q==" + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz", + "integrity": "sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ==" }, "@hapi/bourne": { "version": "1.3.2", @@ -1292,16 +2228,16 @@ } }, "@svgr/webpack": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-4.3.2.tgz", - "integrity": "sha512-F3VE5OvyOWBEd2bF7BdtFRyI6E9it3mN7teDw0JQTlVtc4HZEYiiLSl+Uf9Uub6IYHVGc+qIrxxDyeedkQru2w==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-4.3.3.tgz", + "integrity": "sha512-bjnWolZ6KVsHhgyCoYRFmbd26p8XVbulCzSG53BDQqAr+JOAderYK7CuYrB3bDjHJuF6LJ7Wrr42+goLRV9qIg==", "requires": { "@babel/core": "^7.4.5", "@babel/plugin-transform-react-constant-elements": "^7.0.0", "@babel/preset-env": "^7.4.5", "@babel/preset-react": "^7.0.0", - "@svgr/core": "^4.3.2", - "@svgr/plugin-jsx": "^4.3.2", + "@svgr/core": "^4.3.3", + "@svgr/plugin-jsx": "^4.3.3", "@svgr/plugin-svgo": "^4.3.1", "loader-utils": "^1.2.3" } @@ -1357,6 +2293,21 @@ "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==" }, + "@types/events": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", + "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==" + }, + "@types/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", + "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, "@types/history": { "version": "4.7.3", "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.3.tgz", @@ -1408,11 +2359,29 @@ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.3.tgz", "integrity": "sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==" }, + "@types/jsonwebtoken": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.3.5.tgz", + "integrity": "sha512-VGM1gb+LwsQ5EPevvbvdnKncajBdYqNcrvixBif1BsiDQiSF1q+j4bBTvKC6Bt9n2kqNSx+yNTY2TVJ360E7EQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" + }, "@types/node": { "version": "12.12.7", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.7.tgz", "integrity": "sha512-E6Zn0rffhgd130zbCbAr/JdXfXkoOUFAKNs/rF8qnafSJ8KYaA/j3oz7dcwal+lYjLA7xvdd5J4wdYpCTlP8+w==" }, + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" + }, "@types/prop-types": { "version": "15.7.3", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", @@ -1514,45 +2483,46 @@ "integrity": "sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==" }, "@typescript-eslint/eslint-plugin": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.6.1.tgz", - "integrity": "sha512-Z0rddsGqioKbvqfohg7BwkFC3PuNLsB+GE9QkFza7tiDzuHoy0y823Y+oGNDzxNZrYyLjqkZtCTl4vCqOmEN4g==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.11.0.tgz", + "integrity": "sha512-G2HHA1vpMN0EEbUuWubiCCfd0R3a30BB+UdvnFkxwZIxYEGOrWEXDv8tBFO9f44CWc47Xv9lLM3VSn4ORLI2bA==", "requires": { - "@typescript-eslint/experimental-utils": "2.6.1", - "eslint-utils": "^1.4.2", + "@typescript-eslint/experimental-utils": "2.11.0", + "eslint-utils": "^1.4.3", "functional-red-black-tree": "^1.0.1", - "regexpp": "^2.0.1", + "regexpp": "^3.0.0", "tsutils": "^3.17.1" } }, "@typescript-eslint/experimental-utils": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.6.1.tgz", - "integrity": "sha512-EVrrUhl5yBt7fC7c62lWmriq4MIc49zpN3JmrKqfiFXPXCM5ErfEcZYfKOhZXkW6MBjFcJ5kGZqu1b+lyyExUw==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.11.0.tgz", + "integrity": "sha512-YxcA/y0ZJaCc/fB/MClhcDxHI0nOBB7v2/WxBju2cOTanX7jO9ttQq6Fy4yW9UaY5bPd9xL3cun3lDVqk67sPQ==", "requires": { "@types/json-schema": "^7.0.3", - "@typescript-eslint/typescript-estree": "2.6.1", + "@typescript-eslint/typescript-estree": "2.11.0", "eslint-scope": "^5.0.0" } }, "@typescript-eslint/parser": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.6.1.tgz", - "integrity": "sha512-PDPkUkZ4c7yA+FWqigjwf3ngPUgoLaGjMlFh6TRtbjhqxFBnkElDfckSjm98q9cMr4xRzZ15VrS/xKm6QHYf0w==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.11.0.tgz", + "integrity": "sha512-DyGXeqhb3moMioEFZIHIp7oXBBh7dEfPTzGrlyP0Mi9ScCra4SWEGs3kPd18mG7Sy9Wy8z88zmrw5tSGL6r/6A==", "requires": { "@types/eslint-visitor-keys": "^1.0.0", - "@typescript-eslint/experimental-utils": "2.6.1", - "@typescript-eslint/typescript-estree": "2.6.1", + "@typescript-eslint/experimental-utils": "2.11.0", + "@typescript-eslint/typescript-estree": "2.11.0", "eslint-visitor-keys": "^1.1.0" } }, "@typescript-eslint/typescript-estree": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.6.1.tgz", - "integrity": "sha512-+sTnssW6bcbDZKE8Ce7VV6LdzkQz2Bxk7jzk1J8H1rovoTxnm6iXvYIyncvNsaB/kBCOM63j/LNJfm27bNdUoA==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.11.0.tgz", + "integrity": "sha512-HGY4+d4MagO6cKMcKfIKaTMxcAv7dEVnji2Zi+vi5VV8uWAM631KjAB5GxFcexMYrwKT0EekRiiGK1/Sd7VFGA==", "requires": { "debug": "^4.1.1", - "glob": "^7.1.4", + "eslint-visitor-keys": "^1.1.0", + "glob": "^7.1.6", "is-glob": "^4.0.1", "lodash.unescape": "4.0.1", "semver": "^6.3.0", @@ -1802,6 +2772,15 @@ "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", "dev": true }, + "aggregate-error": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz", + "integrity": "sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA==", + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, "ajv": { "version": "6.10.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", @@ -1834,11 +2813,11 @@ "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==" }, "ansi-escapes": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.2.1.tgz", - "integrity": "sha512-Cg3ymMAdN10wOk/VYfLV7KCQyv7EDirJ64500sU7n9UlmioEtDuU5Gd+hj73hXSU/ex7tHJSssmyftDdkMLO8Q==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.0.tgz", + "integrity": "sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg==", "requires": { - "type-fest": "^0.5.2" + "type-fest": "^0.8.1" } }, "ansi-html": { @@ -1921,12 +2900,37 @@ "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" }, "array-includes": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", - "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.0.tgz", + "integrity": "sha512-ONOEQoKrvXPKk7Su92Co0YMqYO32FfqJTzkKU9u2UpIXyYZIzLSvpdg4AwvSw4mSUW0czu6inK+zby6Oj6gDjQ==", "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.7.0" + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.0" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.0-next.1.tgz", + "integrity": "sha512-7MmGr03N7Rnuid6+wyhD9sHNE2n4tFSwExnU2lQl3lIo2ShXWGePY80zYaoMOmILWv57H0amMjZGHNzzGG70Rw==", + "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.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" + } + }, + "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==" + } } }, "array-union": { @@ -2038,16 +3042,16 @@ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" }, "autoprefixer": { - "version": "9.7.1", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.7.1.tgz", - "integrity": "sha512-w3b5y1PXWlhYulevrTJ0lizkQ5CyqfeU6BIRDbuhsMupstHQOeb1Ur80tcB1zxSu7AwyY/qCQ7Vvqklh31ZBFw==", + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.7.3.tgz", + "integrity": "sha512-8T5Y1C5Iyj6PgkPSFd0ODvK9DIleuPKUPYniNxybS47g2k2wFgLZ46lGQHlBuGKIAEV8fbCDfKCCRS1tvOgc3Q==", "requires": { - "browserslist": "^4.7.2", - "caniuse-lite": "^1.0.30001006", + "browserslist": "^4.8.0", + "caniuse-lite": "^1.0.30001012", "chalk": "^2.4.2", "normalize-range": "^0.1.2", "num2fraction": "^1.2.2", - "postcss": "^7.0.21", + "postcss": "^7.0.23", "postcss-value-parser": "^4.0.2" }, "dependencies": { @@ -2115,11 +3119,22 @@ } }, "axobject-query": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz", - "integrity": "sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.1.1.tgz", + "integrity": "sha512-lF98xa/yvy6j3fBHAgQXIYl+J4eZadOSqsPojemUqClzNbBV38wWGpUbQbVEyf4eUF5yF7eHmGgGA2JiHyjeqw==", "requires": { - "ast-types-flow": "0.0.7" + "@babel/runtime": "^7.7.4", + "@babel/runtime-corejs3": "^7.7.4" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.7.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.6.tgz", + "integrity": "sha512-BWAJxpNVa0QlE5gZdWjSxXtemZyZ9RmrmVozxt3NUXeZhVIJ5ANyqmMc0JDrivBZyxUuQvFxlvH4OWWOogGfUw==", + "requires": { + "regenerator-runtime": "^0.13.2" + } + } } }, "babel-code-frame": { @@ -2255,19 +3270,71 @@ } }, "babel-plugin-macros": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.6.1.tgz", - "integrity": "sha512-6W2nwiXme6j1n2erPOnmRiWfObUhWH7Qw1LMi9XZy8cj+KtESu3T6asZvtk5bMQQjX8te35o7CFueiSdL/2NmQ==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.7.1.tgz", + "integrity": "sha512-HNM284amlKSQ6FddI4jLXD+XTqF0cTYOe5uemOIZxHJHnamC+OhFQ57rMF9sgnYhkJQptVl9U1SKVZsV9/GLQQ==", "requires": { - "@babel/runtime": "^7.4.2", - "cosmiconfig": "^5.2.0", - "resolve": "^1.10.0" + "@babel/runtime": "^7.7.2", + "cosmiconfig": "^6.0.0", + "resolve": "^1.12.0" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.7.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.6.tgz", + "integrity": "sha512-BWAJxpNVa0QlE5gZdWjSxXtemZyZ9RmrmVozxt3NUXeZhVIJ5ANyqmMc0JDrivBZyxUuQvFxlvH4OWWOogGfUw==", + "requires": { + "regenerator-runtime": "^0.13.2" + } + }, + "cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + } + }, + "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==", + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "parse-json": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", + "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==", + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1", + "lines-and-columns": "^1.1.6" + } + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" + }, + "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==" + } } }, "babel-plugin-named-asset-import": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.4.tgz", - "integrity": "sha512-S6d+tEzc5Af1tKIMbsf2QirCcPdQ+mKUCY2H1nJj1DyA1ShwpsoxEOAwbWsG5gcXNV/olpvQd9vrUWRx4bnhpw==" + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.5.tgz", + "integrity": "sha512-sGhfINU+AuMw9oFAdIn/nD5sem3pn/WgxAfDZ//Q3CnF+5uaho7C7shh2rKLk6sKE/XkfmyibghocwKdVjLIKg==" }, "babel-plugin-styled-components": { "version": "1.10.6", @@ -2314,87 +3381,171 @@ } }, "babel-preset-react-app": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/babel-preset-react-app/-/babel-preset-react-app-9.0.2.tgz", - "integrity": "sha512-aXD+CTH8Chn8sNJr4tO/trWKqe5sSE4hdO76j9fhVezJSzmpWYWUSc5JoPmdSxADwef5kQFNGKXd433vvkd2VQ==", - "requires": { - "@babel/core": "7.6.0", - "@babel/plugin-proposal-class-properties": "7.5.5", - "@babel/plugin-proposal-decorators": "7.6.0", - "@babel/plugin-proposal-object-rest-spread": "7.5.5", - "@babel/plugin-syntax-dynamic-import": "7.2.0", - "@babel/plugin-transform-destructuring": "7.6.0", - "@babel/plugin-transform-flow-strip-types": "7.4.4", - "@babel/plugin-transform-react-display-name": "7.2.0", - "@babel/plugin-transform-runtime": "7.6.0", - "@babel/preset-env": "7.6.0", - "@babel/preset-react": "7.0.0", - "@babel/preset-typescript": "7.6.0", - "@babel/runtime": "7.6.0", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-react-app/-/babel-preset-react-app-9.1.0.tgz", + "integrity": "sha512-0qMOv/pCcCQWxX1eNyKD9GlzZTdzZIK/Pq3O6TGe65tZSJTSplw1pFlaPujm0GjBj4g3GeCQbP08vvzlH7OGHg==", + "requires": { + "@babel/core": "7.7.4", + "@babel/plugin-proposal-class-properties": "7.7.4", + "@babel/plugin-proposal-decorators": "7.7.4", + "@babel/plugin-proposal-nullish-coalescing-operator": "7.7.4", + "@babel/plugin-proposal-numeric-separator": "7.7.4", + "@babel/plugin-proposal-object-rest-spread": "7.7.4", + "@babel/plugin-proposal-optional-chaining": "7.7.4", + "@babel/plugin-syntax-dynamic-import": "7.7.4", + "@babel/plugin-transform-destructuring": "7.7.4", + "@babel/plugin-transform-flow-strip-types": "7.7.4", + "@babel/plugin-transform-react-display-name": "7.7.4", + "@babel/plugin-transform-runtime": "7.7.4", + "@babel/preset-env": "7.7.4", + "@babel/preset-react": "7.7.4", + "@babel/preset-typescript": "7.7.4", + "@babel/runtime": "7.7.4", "babel-plugin-dynamic-import-node": "2.3.0", - "babel-plugin-macros": "2.6.1", + "babel-plugin-macros": "2.7.1", "babel-plugin-transform-react-remove-prop-types": "0.4.24" }, "dependencies": { - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz", - "integrity": "sha512-F2DxJJSQ7f64FyTVl5cw/9MWn6naXGdk3Q3UhDbFEEHv+EilCPoeRD3Zh/Utx1CJz4uyKlQ4uH+bJPbEhMV7Zw==", + "@babel/core": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.4.tgz", + "integrity": "sha512-+bYbx56j4nYBmpsWtnPUsKW3NdnYxbqyfrP2w9wILBuHzdfIKz9prieZK0DFPyIzkjYVUe4QkusGL07r5pXznQ==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.2.0" + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.7.4", + "@babel/helpers": "^7.7.4", + "@babel/parser": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@babel/types": "^7.7.4", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "json5": "^2.1.0", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + } + }, + "@babel/generator": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.4.tgz", + "integrity": "sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg==", + "requires": { + "@babel/types": "^7.7.4", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + } + }, + "@babel/helper-function-name": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz", + "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==", + "requires": { + "@babel/helper-get-function-arity": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz", + "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/helper-module-imports": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.7.4.tgz", + "integrity": "sha512-dGcrX6K9l8258WFjyDLJwuVKxR4XZfU0/vTUgOQYWEnRD8mgr+p4d6fCUMq/ys0h4CCt/S5JhbvtyErjWouAUQ==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz", + "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/helpers": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.7.4.tgz", + "integrity": "sha512-ak5NGZGJ6LV85Q1Zc9gn2n+ayXOizryhjSUBTdu5ih1tlVCJeuQENzc4ItyCVhINVXvIT/ZQ4mheGIsfBkpskg==", + "requires": { + "@babel/template": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/parser": { + "version": "7.7.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.5.tgz", + "integrity": "sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig==" + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.7.4.tgz", + "integrity": "sha512-mObR+r+KZq0XhRVS2BrBKBpr5jqrqzlPvS9C9vuOf5ilSwzloAl7RPWLrgKdWS6IreaVrjHxTjtyqFiOisaCwg==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/preset-env": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.6.0.tgz", - "integrity": "sha512-1efzxFv/TcPsNXlRhMzRnkBFMeIqBBgzwmZwlFDw5Ubj0AGLeufxugirwZmkkX/ayi3owsSqoQ4fw8LkfK9SYg==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.7.4.tgz", + "integrity": "sha512-Dg+ciGJjwvC1NIe/DGblMbcGq1HOtKbw8RLl4nIjlfcILKEOkWT/vRqPpumswABEBVudii6dnVwrBtzD7ibm4g==", "requires": { - "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-module-imports": "^7.7.4", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-async-generator-functions": "^7.2.0", - "@babel/plugin-proposal-dynamic-import": "^7.5.0", - "@babel/plugin-proposal-json-strings": "^7.2.0", - "@babel/plugin-proposal-object-rest-spread": "^7.5.5", - "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-syntax-async-generators": "^7.2.0", - "@babel/plugin-syntax-dynamic-import": "^7.2.0", - "@babel/plugin-syntax-json-strings": "^7.2.0", - "@babel/plugin-syntax-object-rest-spread": "^7.2.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", - "@babel/plugin-transform-arrow-functions": "^7.2.0", - "@babel/plugin-transform-async-to-generator": "^7.5.0", - "@babel/plugin-transform-block-scoped-functions": "^7.2.0", - "@babel/plugin-transform-block-scoping": "^7.6.0", - "@babel/plugin-transform-classes": "^7.5.5", - "@babel/plugin-transform-computed-properties": "^7.2.0", - "@babel/plugin-transform-destructuring": "^7.6.0", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/plugin-transform-duplicate-keys": "^7.5.0", - "@babel/plugin-transform-exponentiation-operator": "^7.2.0", - "@babel/plugin-transform-for-of": "^7.4.4", - "@babel/plugin-transform-function-name": "^7.4.4", - "@babel/plugin-transform-literals": "^7.2.0", - "@babel/plugin-transform-member-expression-literals": "^7.2.0", - "@babel/plugin-transform-modules-amd": "^7.5.0", - "@babel/plugin-transform-modules-commonjs": "^7.6.0", - "@babel/plugin-transform-modules-systemjs": "^7.5.0", - "@babel/plugin-transform-modules-umd": "^7.2.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.6.0", - "@babel/plugin-transform-new-target": "^7.4.4", - "@babel/plugin-transform-object-super": "^7.5.5", - "@babel/plugin-transform-parameters": "^7.4.4", - "@babel/plugin-transform-property-literals": "^7.2.0", - "@babel/plugin-transform-regenerator": "^7.4.5", - "@babel/plugin-transform-reserved-words": "^7.2.0", - "@babel/plugin-transform-shorthand-properties": "^7.2.0", - "@babel/plugin-transform-spread": "^7.2.0", - "@babel/plugin-transform-sticky-regex": "^7.2.0", - "@babel/plugin-transform-template-literals": "^7.4.4", - "@babel/plugin-transform-typeof-symbol": "^7.2.0", - "@babel/plugin-transform-unicode-regex": "^7.4.4", - "@babel/types": "^7.6.0", + "@babel/plugin-proposal-async-generator-functions": "^7.7.4", + "@babel/plugin-proposal-dynamic-import": "^7.7.4", + "@babel/plugin-proposal-json-strings": "^7.7.4", + "@babel/plugin-proposal-object-rest-spread": "^7.7.4", + "@babel/plugin-proposal-optional-catch-binding": "^7.7.4", + "@babel/plugin-proposal-unicode-property-regex": "^7.7.4", + "@babel/plugin-syntax-async-generators": "^7.7.4", + "@babel/plugin-syntax-dynamic-import": "^7.7.4", + "@babel/plugin-syntax-json-strings": "^7.7.4", + "@babel/plugin-syntax-object-rest-spread": "^7.7.4", + "@babel/plugin-syntax-optional-catch-binding": "^7.7.4", + "@babel/plugin-syntax-top-level-await": "^7.7.4", + "@babel/plugin-transform-arrow-functions": "^7.7.4", + "@babel/plugin-transform-async-to-generator": "^7.7.4", + "@babel/plugin-transform-block-scoped-functions": "^7.7.4", + "@babel/plugin-transform-block-scoping": "^7.7.4", + "@babel/plugin-transform-classes": "^7.7.4", + "@babel/plugin-transform-computed-properties": "^7.7.4", + "@babel/plugin-transform-destructuring": "^7.7.4", + "@babel/plugin-transform-dotall-regex": "^7.7.4", + "@babel/plugin-transform-duplicate-keys": "^7.7.4", + "@babel/plugin-transform-exponentiation-operator": "^7.7.4", + "@babel/plugin-transform-for-of": "^7.7.4", + "@babel/plugin-transform-function-name": "^7.7.4", + "@babel/plugin-transform-literals": "^7.7.4", + "@babel/plugin-transform-member-expression-literals": "^7.7.4", + "@babel/plugin-transform-modules-amd": "^7.7.4", + "@babel/plugin-transform-modules-commonjs": "^7.7.4", + "@babel/plugin-transform-modules-systemjs": "^7.7.4", + "@babel/plugin-transform-modules-umd": "^7.7.4", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.7.4", + "@babel/plugin-transform-new-target": "^7.7.4", + "@babel/plugin-transform-object-super": "^7.7.4", + "@babel/plugin-transform-parameters": "^7.7.4", + "@babel/plugin-transform-property-literals": "^7.7.4", + "@babel/plugin-transform-regenerator": "^7.7.4", + "@babel/plugin-transform-reserved-words": "^7.7.4", + "@babel/plugin-transform-shorthand-properties": "^7.7.4", + "@babel/plugin-transform-spread": "^7.7.4", + "@babel/plugin-transform-sticky-regex": "^7.7.4", + "@babel/plugin-transform-template-literals": "^7.7.4", + "@babel/plugin-transform-typeof-symbol": "^7.7.4", + "@babel/plugin-transform-unicode-regex": "^7.7.4", + "@babel/types": "^7.7.4", "browserslist": "^4.6.0", "core-js-compat": "^3.1.1", "invariant": "^2.2.2", @@ -2402,16 +3553,48 @@ "semver": "^5.5.0" } }, - "@babel/preset-react": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.0.0.tgz", - "integrity": "sha512-oayxyPS4Zj+hF6Et11BwuBkmpgT/zMxyuZgFrMeZID6Hdh3dGlk4sHCAhdBCpuCKW2ppBfl2uCCetlrUIJRY3w==", + "@babel/runtime": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.4.tgz", + "integrity": "sha512-r24eVUUr0QqNZa+qrImUk8fn5SPhHq+IfYvIoIMg0do3GdK9sMdiLKP3GYVVaxpPKORgm8KRKaNTEhAjgIpLMw==", "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-transform-react-display-name": "^7.0.0", - "@babel/plugin-transform-react-jsx": "^7.0.0", - "@babel/plugin-transform-react-jsx-self": "^7.0.0", - "@babel/plugin-transform-react-jsx-source": "^7.0.0" + "regenerator-runtime": "^0.13.2" + } + }, + "@babel/template": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz", + "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/traverse": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz", + "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==", + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.7.4", + "@babel/helper-function-name": "^7.7.4", + "@babel/helper-split-export-declaration": "^7.7.4", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } + }, + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" } }, "semver": { @@ -2431,9 +3614,9 @@ }, "dependencies": { "core-js": { - "version": "2.6.10", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", - "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==" + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" }, "regenerator-runtime": { "version": "0.11.1", @@ -2569,9 +3752,9 @@ "dev": true }, "bluebird": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.1.tgz", - "integrity": "sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==" + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "bn.js": { "version": "4.11.8", @@ -2765,13 +3948,13 @@ } }, "browserslist": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.7.2.tgz", - "integrity": "sha512-uZavT/gZXJd2UTi9Ov7/Z340WOSQ3+m1iBVRUknf+okKxonL9P83S3ctiBDtuRmRu8PiCHjqyueqQ9HYlJhxiw==", + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.8.2.tgz", + "integrity": "sha512-+M4oeaTplPm/f1pXDw84YohEv7B1i/2Aisei8s4s6k3QsoSHa7i5sz8u/cGQkkatCPxMASKxPualR4wwYgVboA==", "requires": { - "caniuse-lite": "^1.0.30001004", - "electron-to-chromium": "^1.3.295", - "node-releases": "^1.1.38" + "caniuse-lite": "^1.0.30001015", + "electron-to-chromium": "^1.3.322", + "node-releases": "^1.1.42" } }, "bs-logger": { @@ -2801,6 +3984,11 @@ "isarray": "^1.0.0" } }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -2827,25 +4015,38 @@ "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" }, "cacache": { - "version": "12.0.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz", - "integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==", + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-13.0.1.tgz", + "integrity": "sha512-5ZvAxd05HDDU+y9BVvcqYu2LLXmPnQ0hW62h32g4xBTgL/MppR4/04NHfj/ycM2y6lmTnbw6HVi+1eN0Psba6w==", "requires": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", + "chownr": "^1.1.2", "figgy-pudding": "^3.5.1", + "fs-minipass": "^2.0.0", "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "infer-owner": "^1.0.3", + "graceful-fs": "^4.2.2", + "infer-owner": "^1.0.4", "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", + "minipass": "^3.0.0", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", "mkdirp": "^0.5.1", "move-concurrently": "^1.0.1", + "p-map": "^3.0.0", "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" + "rimraf": "^2.7.1", + "ssri": "^7.0.0", + "unique-filename": "^1.1.1" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "requires": { + "glob": "^7.1.3" + } + } } }, "cache-base": { @@ -2927,9 +4128,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001008", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001008.tgz", - "integrity": "sha512-b8DJyb+VVXZGRgJUa30cbk8gKHZ3LOZTBLaUEEVr2P4xpmFigOCc62CO4uzquW641Ouq1Rm9N+rWLWdSYDaDIw==" + "version": "1.0.30001015", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001015.tgz", + "integrity": "sha512-/xL2AbW/XWHNu1gnIrO8UitBGoFthcsDgU9VLK1/dpsoxbaD5LscHozKze05R6WLsBvLhqv78dAPozMFQBYLbQ==" }, "capture-exit": { "version": "2.0.0", @@ -2995,26 +4196,22 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "resolved": false, - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "bundled": true, "optional": true }, "ansi-regex": { "version": "2.1.1", - "resolved": false, - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "bundled": true, "optional": true }, "aproba": { "version": "1.2.0", - "resolved": false, - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "bundled": true, "optional": true }, "are-we-there-yet": { "version": "1.1.5", - "resolved": false, - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "bundled": true, "optional": true, "requires": { "delegates": "^1.0.0", @@ -3023,14 +4220,12 @@ }, "balanced-match": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "bundled": true, "optional": true }, "brace-expansion": { "version": "1.1.11", - "resolved": false, - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "bundled": true, "optional": true, "requires": { "balanced-match": "^1.0.0", @@ -3039,38 +4234,32 @@ }, "chownr": { "version": "1.1.1", - "resolved": false, - "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", + "bundled": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "resolved": false, - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "bundled": true, "optional": true }, "concat-map": { "version": "0.0.1", - "resolved": false, - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "bundled": true, "optional": true }, "console-control-strings": { "version": "1.1.0", - "resolved": false, - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "bundled": true, "optional": true }, "core-util-is": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "bundled": true, "optional": true }, "debug": { "version": "4.1.1", - "resolved": false, - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "bundled": true, "optional": true, "requires": { "ms": "^2.1.1" @@ -3078,26 +4267,22 @@ }, "deep-extend": { "version": "0.6.0", - "resolved": false, - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "bundled": true, "optional": true }, "delegates": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "bundled": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "resolved": false, - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "bundled": true, "optional": true }, "fs-minipass": { "version": "1.2.5", - "resolved": false, - "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", + "bundled": true, "optional": true, "requires": { "minipass": "^2.2.1" @@ -3105,14 +4290,12 @@ }, "fs.realpath": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "bundled": true, "optional": true }, "gauge": { "version": "2.7.4", - "resolved": false, - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "bundled": true, "optional": true, "requires": { "aproba": "^1.0.3", @@ -3127,8 +4310,7 @@ }, "glob": { "version": "7.1.3", - "resolved": false, - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "bundled": true, "optional": true, "requires": { "fs.realpath": "^1.0.0", @@ -3141,14 +4323,12 @@ }, "has-unicode": { "version": "2.0.1", - "resolved": false, - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "bundled": true, "optional": true }, "iconv-lite": { "version": "0.4.24", - "resolved": false, - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "bundled": true, "optional": true, "requires": { "safer-buffer": ">= 2.1.2 < 3" @@ -3156,8 +4336,7 @@ }, "ignore-walk": { "version": "3.0.1", - "resolved": false, - "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", + "bundled": true, "optional": true, "requires": { "minimatch": "^3.0.4" @@ -3165,8 +4344,7 @@ }, "inflight": { "version": "1.0.6", - "resolved": false, - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "bundled": true, "optional": true, "requires": { "once": "^1.3.0", @@ -3175,20 +4353,17 @@ }, "inherits": { "version": "2.0.3", - "resolved": false, - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "bundled": true, "optional": true }, "ini": { "version": "1.3.5", - "resolved": false, - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "bundled": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "bundled": true, "optional": true, "requires": { "number-is-nan": "^1.0.0" @@ -3196,14 +4371,12 @@ }, "isarray": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "bundled": true, "optional": true }, "minimatch": { "version": "3.0.4", - "resolved": false, - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "bundled": true, "optional": true, "requires": { "brace-expansion": "^1.1.7" @@ -3211,14 +4384,12 @@ }, "minimist": { "version": "0.0.8", - "resolved": false, - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "bundled": true, "optional": true }, "minipass": { "version": "2.3.5", - "resolved": false, - "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", + "bundled": true, "optional": true, "requires": { "safe-buffer": "^5.1.2", @@ -3227,8 +4398,7 @@ }, "minizlib": { "version": "1.2.1", - "resolved": false, - "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", + "bundled": true, "optional": true, "requires": { "minipass": "^2.2.1" @@ -3236,8 +4406,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": false, - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "bundled": true, "optional": true, "requires": { "minimist": "0.0.8" @@ -3245,14 +4414,12 @@ }, "ms": { "version": "2.1.1", - "resolved": false, - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "bundled": true, "optional": true }, "needle": { "version": "2.3.0", - "resolved": false, - "integrity": "sha512-QBZu7aAFR0522EyaXZM0FZ9GLpq6lvQ3uq8gteiDUp7wKdy0lSd2hPlgFwVuW1CBkfEs9PfDQsQzZghLs/psdg==", + "bundled": true, "optional": true, "requires": { "debug": "^4.1.0", @@ -3262,8 +4429,7 @@ }, "node-pre-gyp": { "version": "0.12.0", - "resolved": false, - "integrity": "sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==", + "bundled": true, "optional": true, "requires": { "detect-libc": "^1.0.2", @@ -3280,8 +4446,7 @@ }, "nopt": { "version": "4.0.1", - "resolved": false, - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "bundled": true, "optional": true, "requires": { "abbrev": "1", @@ -3290,14 +4455,12 @@ }, "npm-bundled": { "version": "1.0.6", - "resolved": false, - "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==", + "bundled": true, "optional": true }, "npm-packlist": { "version": "1.4.1", - "resolved": false, - "integrity": "sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==", + "bundled": true, "optional": true, "requires": { "ignore-walk": "^3.0.1", @@ -3306,8 +4469,7 @@ }, "npmlog": { "version": "4.1.2", - "resolved": false, - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "bundled": true, "optional": true, "requires": { "are-we-there-yet": "~1.1.2", @@ -3317,21 +4479,18 @@ } }, "number-is-nan": { - "version": "1.0.1", - "resolved": false, - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "version": "1.0.1", + "bundled": true, "optional": true }, "object-assign": { "version": "4.1.1", - "resolved": false, - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "bundled": true, "optional": true }, "once": { "version": "1.4.0", - "resolved": false, - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "bundled": true, "optional": true, "requires": { "wrappy": "1" @@ -3339,20 +4498,17 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "bundled": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "bundled": true, "optional": true }, "osenv": { "version": "0.1.5", - "resolved": false, - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "bundled": true, "optional": true, "requires": { "os-homedir": "^1.0.0", @@ -3361,20 +4517,17 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": false, - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "bundled": true, "optional": true }, "process-nextick-args": { "version": "2.0.0", - "resolved": false, - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "bundled": true, "optional": true }, "rc": { "version": "1.2.8", - "resolved": false, - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "bundled": true, "optional": true, "requires": { "deep-extend": "^0.6.0", @@ -3385,16 +4538,14 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": false, - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "bundled": true, "optional": true } } }, "readable-stream": { "version": "2.3.6", - "resolved": false, - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "bundled": true, "optional": true, "requires": { "core-util-is": "~1.0.0", @@ -3408,8 +4559,7 @@ }, "rimraf": { "version": "2.6.3", - "resolved": false, - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "bundled": true, "optional": true, "requires": { "glob": "^7.1.3" @@ -3417,44 +4567,37 @@ }, "safe-buffer": { "version": "5.1.2", - "resolved": false, - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "bundled": true, "optional": true }, "safer-buffer": { "version": "2.1.2", - "resolved": false, - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "bundled": true, "optional": true }, "sax": { "version": "1.2.4", - "resolved": false, - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "bundled": true, "optional": true }, "semver": { "version": "5.7.0", - "resolved": false, - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "bundled": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "resolved": false, - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "bundled": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "resolved": false, - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "bundled": true, "optional": true }, "string-width": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "bundled": true, "optional": true, "requires": { "code-point-at": "^1.0.0", @@ -3464,8 +4607,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": false, - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "bundled": true, "optional": true, "requires": { "safe-buffer": "~5.1.0" @@ -3473,8 +4615,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": false, - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "bundled": true, "optional": true, "requires": { "ansi-regex": "^2.0.0" @@ -3482,14 +4623,12 @@ }, "strip-json-comments": { "version": "2.0.1", - "resolved": false, - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "bundled": true, "optional": true }, "tar": { "version": "4.4.8", - "resolved": false, - "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", + "bundled": true, "optional": true, "requires": { "chownr": "^1.1.1", @@ -3503,14 +4642,12 @@ }, "util-deprecate": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "bundled": true, "optional": true }, "wide-align": { "version": "1.1.3", - "resolved": false, - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "bundled": true, "optional": true, "requires": { "string-width": "^1.0.2 || 2" @@ -3518,14 +4655,12 @@ }, "wrappy": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "bundled": true, "optional": true }, "yallist": { "version": "3.0.3", - "resolved": false, - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "bundled": true, "optional": true } } @@ -3619,6 +4754,11 @@ } } }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" + }, "cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -3936,19 +5076,24 @@ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" }, "core-js": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz", - "integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==" + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.5.0.tgz", + "integrity": "sha512-Ifh3kj78gzQ7NAoJXeTu+XwzDld0QRIwjBLRqAMhuLhP3d2Av5wmgE9ycfnvK6NAEjTkQ1sDPeoEZAWO3Hx1Uw==" }, "core-js-compat": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.4.0.tgz", - "integrity": "sha512-pgQUcgT2+v9/yxHgMynYjNj7nmxLRXv3UC39rjCjDwpe63ev2rioQTju1PKLYUBbPCQQvZNWvQC8tBJd65q11g==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.5.0.tgz", + "integrity": "sha512-E7iJB72svRjJTnm9HDvujzNVMCm3ZcDYEedkJ/sDTNsy/0yooCd9Cg7GSzE7b4e0LfIkjijdB1tqg0pGwxWeWg==", "requires": { - "browserslist": "^4.7.2", + "browserslist": "^4.8.2", "semver": "^6.3.0" } }, + "core-js-pure": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.5.0.tgz", + "integrity": "sha512-wB0QtKAofWigiISuT1Tej3hKgq932fB//Lf1VoPbiLpTYlHY0nIDhgF+q1na0DAKFHH5wGCirkAknOmDN8ijXA==" + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -4108,27 +5253,33 @@ } }, "css-loader": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-2.1.1.tgz", - "integrity": "sha512-OcKJU/lt232vl1P9EEDamhoO9iKY3tIjY5GU+XDLblAykTdgs6Ux9P1hTHve8nFKy5KPpOXOsVI/hIwi3841+w==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.2.0.tgz", + "integrity": "sha512-QTF3Ud5H7DaZotgdcJjGMvyDj5F3Pn1j/sC6VBEOVp94cbwqyIBdcs/quzj4MC1BKQSrTpQznegH/5giYbhnCQ==", "requires": { - "camelcase": "^5.2.0", - "icss-utils": "^4.1.0", + "camelcase": "^5.3.1", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", "loader-utils": "^1.2.3", "normalize-path": "^3.0.0", - "postcss": "^7.0.14", + "postcss": "^7.0.17", "postcss-modules-extract-imports": "^2.0.0", - "postcss-modules-local-by-default": "^2.0.6", + "postcss-modules-local-by-default": "^3.0.2", "postcss-modules-scope": "^2.1.0", - "postcss-modules-values": "^2.0.0", - "postcss-value-parser": "^3.3.0", - "schema-utils": "^1.0.0" + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.0.0", + "schema-utils": "^2.0.0" }, "dependencies": { "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "postcss-value-parser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.2.tgz", + "integrity": "sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ==" } } }, @@ -4444,16 +5595,17 @@ } }, "del": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", - "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", "requires": { + "@types/glob": "^7.1.1", "globby": "^6.1.0", - "is-path-cwd": "^1.0.0", - "is-path-in-cwd": "^1.0.0", - "p-map": "^1.1.1", - "pify": "^3.0.0", - "rimraf": "^2.2.8" + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" }, "dependencies": { "globby": { @@ -4474,6 +5626,16 @@ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==" + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" } } }, @@ -4488,9 +5650,9 @@ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" }, "des.js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", - "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", "requires": { "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0" @@ -4659,8 +5821,7 @@ "dotenv": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", - "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==", - "dev": true + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" }, "dotenv-expand": { "version": "5.1.0", @@ -4716,20 +5877,28 @@ "safer-buffer": "^2.1.0" } }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "electron-to-chromium": { - "version": "1.3.306", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.306.tgz", - "integrity": "sha512-frDqXvrIROoYvikSKTIKbHbzO6M3/qC6kCIt/1FOa9kALe++c4VAJnwjSFvf1tYLEUsP2n9XZ4XSCyqc3l7A/A==" + "version": "1.3.322", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.322.tgz", + "integrity": "sha512-Tc8JQEfGQ1MzfSzI/bTlSr7btJv/FFO7Yh6tanqVmIWOuNCu6/D1MilIEgLtmWqIrsv+o4IjpLAhgMBr/ncNAA==" }, "elliptic": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.1.tgz", - "integrity": "sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", + "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==", "requires": { "bn.js": "^4.4.0", "brorand": "^1.0.1", @@ -4935,12 +6104,12 @@ } }, "es5-ext": { - "version": "0.10.52", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.52.tgz", - "integrity": "sha512-bWCbE9fbpYQY4CU6hJbJ1vSz70EClMlDgJ7BmwI+zEJhxrwjesZRPglGJlsZhu0334U3hI+gaspwksH9IGD6ag==", + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", "requires": { "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.2", + "es6-symbol": "~3.1.3", "next-tick": "~1.0.0" } }, @@ -4999,9 +6168,9 @@ } }, "eslint": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.6.0.tgz", - "integrity": "sha512-PpEBq7b6qY/qrOmpYQ/jTMDYfuQMELR4g4WI1M/NaSDDD/bdcMb+dj4Hgks7p41kW2caXsPsEZAEAyAgjVVC0g==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.7.2.tgz", + "integrity": "sha512-qMlSWJaCSxDFr8fBPvJM9kJwbazrhNcBU3+DszDW1OlEwKBBRWsJc7NJFelvwQpanHCR14cOLD41x8Eqvo3Nng==", "requires": { "@babel/code-frame": "^7.0.0", "ajv": "^6.10.0", @@ -5018,7 +6187,7 @@ "file-entry-cache": "^5.0.1", "functional-red-black-tree": "^1.0.1", "glob-parent": "^5.0.0", - "globals": "^11.7.0", + "globals": "^12.1.0", "ignore": "^4.0.6", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", @@ -5031,7 +6200,7 @@ "minimatch": "^3.0.4", "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", - "optionator": "^0.8.2", + "optionator": "^0.8.3", "progress": "^2.0.0", "regexpp": "^2.0.1", "semver": "^6.1.2", @@ -5042,15 +6211,28 @@ "v8-compile-cache": "^2.0.3" }, "dependencies": { + "globals": { + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.3.0.tgz", + "integrity": "sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw==", + "requires": { + "type-fest": "^0.8.1" + } + }, "import-fresh": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz", - "integrity": "sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==", + "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==", "requires": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==" + }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -5059,9 +6241,9 @@ } }, "eslint-config-react-app": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-5.0.2.tgz", - "integrity": "sha512-VhlESAQM83uULJ9jsvcKxx2Ab0yrmjUt8kDz5DyhTQufqWE0ssAnejlWri5LXv25xoXfdqOyeDPdfJS9dXKagQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-5.1.0.tgz", + "integrity": "sha512-hBaxisHC6HXRVvxX+/t1n8mOdmCVIKgkXsf2WoUkJi7upHJTwYTsdCmx01QPOjKNT34QMQQ9sL0tVBlbiMFjxA==", "requires": { "confusing-browser-globals": "^1.0.9" } @@ -5100,35 +6282,14 @@ "loader-utils": "^1.2.3", "object-hash": "^1.3.1", "schema-utils": "^2.2.0" - }, - "dependencies": { - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "schema-utils": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.5.0.tgz", - "integrity": "sha512-32ISrwW2scPXHUSusP8qMg5dLUawKkyV+/qIEV9JdXKx+rsM6mi8vZY8khg2M69Qom16rtroWXD3Ybtiws38gQ==", - "requires": { - "ajv": "^6.10.2", - "ajv-keywords": "^3.4.1" - } - } } }, "eslint-module-utils": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz", - "integrity": "sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.5.0.tgz", + "integrity": "sha512-kCo8pZaNz2dsAW7nCUjuVoI11EBXXpIzfNxmaoLhXoRDOnqXLC4iSGVRdZPhOitfbdEfMEfKOiENaK6wDPZEGw==", "requires": { - "debug": "^2.6.8", + "debug": "^2.6.9", "pkg-dir": "^2.0.0" }, "dependencies": { @@ -5356,19 +6517,19 @@ } }, "eslint-plugin-react": { - "version": "7.14.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.14.3.tgz", - "integrity": "sha512-EzdyyBWC4Uz2hPYBiEJrKCUi2Fn+BJ9B/pJQcjw5X+x/H2Nm59S4MJIvL4O5NEE0+WbnQwEBxWY03oUk+Bc3FA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.16.0.tgz", + "integrity": "sha512-GacBAATewhhptbK3/vTP09CbFrgUJmBSaaRcWdbQLFvUZy9yVcQxigBNHGPU/KE2AyHpzj3AWXpxoMTsIDiHug==", "requires": { "array-includes": "^3.0.3", "doctrine": "^2.1.0", "has": "^1.0.3", - "jsx-ast-utils": "^2.1.0", + "jsx-ast-utils": "^2.2.1", "object.entries": "^1.1.0", "object.fromentries": "^2.0.0", "object.values": "^1.1.0", "prop-types": "^15.7.2", - "resolve": "^1.10.1" + "resolve": "^1.12.0" }, "dependencies": { "doctrine": { @@ -5626,9 +6787,9 @@ } }, "ext": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.2.0.tgz", - "integrity": "sha512-0ccUQK/9e3NreLFg6K6np8aPyRgwycx+oFGtfx1dSp7Wj00Ozw9r05FgBRlzjf2XBM7LAzwgLyDscRrtSU91hA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", "requires": { "type": "^2.0.0" }, @@ -5793,9 +6954,9 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, "faye-websocket": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", - "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", "requires": { "websocket-driver": ">=0.5.1" } @@ -5830,12 +6991,12 @@ } }, "file-loader": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-3.0.1.tgz", - "integrity": "sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-4.3.0.tgz", + "integrity": "sha512-aKrYPYjF1yG3oX0kWRrqrSMfgftm7oJW5M+m4owoldH5C51C0RkIwB++JbRvEW3IU6/ZG5n8UvEcdgwOt2UOWA==", "requires": { - "loader-utils": "^1.0.2", - "schema-utils": "^1.0.0" + "loader-utils": "^1.2.3", + "schema-utils": "^2.5.0" } }, "filesize": { @@ -6001,9 +7162,9 @@ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, "fork-ts-checker-webpack-plugin": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-1.5.0.tgz", - "integrity": "sha512-zEhg7Hz+KhZlBhILYpXy+Beu96gwvkROWJiTXOCyOOMMrdBIRPvsBpBqgTI4jfJGrJXcqGwJR8zsBGDmzY0jsA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-3.1.0.tgz", + "integrity": "sha512-6OkRfjuNMNqb14f01xokcWcKV5Ekknc2FvziNpcTYru+kxIYFA2MtuuBI19MHThZnjSBhoi35Dcq+I0oUkFjmQ==", "requires": { "babel-code-frame": "^6.22.0", "chalk": "^2.4.1", @@ -6084,15 +7245,23 @@ } }, "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "requires": { - "graceful-fs": "^4.1.2", + "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, + "fs-minipass": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.0.0.tgz", + "integrity": "sha512-40Qz+LFXmd9tzYVnnBmZvFfvAADfUA14TXPK1s7IfElJTIZ97rA8w4Kin7Wt5JBrC3ShnnFJO/5vPjPEeJIq9A==", + "requires": { + "minipass": "^3.0.0" + } + }, "fs-write-stream-atomic": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", @@ -6134,9 +7303,9 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.0.7.tgz", - "integrity": "sha512-a7YT0SV3RB+DjYcppwVDLtn13UQnmg0SWZS7ezZD0UjnLwXmy8Zm21GMVGLaFGimIqcvyMQaOJBrop8MyOp1kQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", + "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", "optional": true }, "function-bind": { @@ -6155,9 +7324,9 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-own-enumerable-property-symbols": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.1.tgz", - "integrity": "sha512-09/VS4iek66Dh2bctjRkowueRJbY1JDGR1L/zRxO1Qk8Uxs6PnqaNSqalpizPT+CDjre3hnEsuzvhgomz9qYrA==" + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" }, "get-stream": { "version": "4.1.0", @@ -6674,11 +7843,6 @@ "safer-buffer": ">= 2.1.2 < 3" } }, - "icss-replace-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", - "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=" - }, "icss-utils": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", @@ -6754,6 +7918,11 @@ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, + "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==" + }, "indexes-of": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", @@ -6985,24 +8154,24 @@ "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" }, "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=" + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==" }, "is-path-in-cwd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", - "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", "requires": { - "is-path-inside": "^1.0.0" + "is-path-inside": "^2.1.0" } }, "is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", "requires": { - "path-is-inside": "^1.0.1" + "path-is-inside": "^1.0.2" } }, "is-plain-obj": { @@ -7293,9 +8462,9 @@ }, "dependencies": { "acorn": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz", - "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==" + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", + "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==" }, "jsdom": { "version": "14.1.0", @@ -8164,12 +9333,13 @@ } }, "jest-watch-typeahead": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-0.4.0.tgz", - "integrity": "sha512-bJR/HPNgOQnkmttg1OkBIrYFAYuxFxExtgQh67N2qPvaWGVC8TCkedRNPKBfmZfVXFD3u2sCH+9OuS5ApBfCgA==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-0.4.2.tgz", + "integrity": "sha512-f7VpLebTdaXs81rg/oj4Vg/ObZy2QtGzAmGLNsqUS5G5KtSN68tFcIsbvNODfNyQxU78g7D8x77o3bgfBTR+2Q==", "requires": { "ansi-escapes": "^4.2.1", "chalk": "^2.4.1", + "jest-regex-util": "^24.9.0", "jest-watcher": "^24.3.0", "slash": "^3.0.0", "string-length": "^3.1.0", @@ -8360,6 +9530,30 @@ "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" }, + "jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -8380,6 +9574,25 @@ "object.assign": "^4.1.0" } }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "killable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", @@ -8439,6 +9652,11 @@ "type-check": "~0.3.2" } }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" + }, "load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", @@ -8540,11 +9758,46 @@ "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + }, "lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", @@ -8601,6 +9854,13 @@ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "requires": { "yallist": "^3.0.2" + }, + "dependencies": { + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + } } }, "make-dir": { @@ -8853,6 +10113,18 @@ "normalize-url": "1.9.1", "schema-utils": "^1.0.0", "webpack-sources": "^1.1.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } } }, "minimalistic-assert": { @@ -8878,6 +10150,38 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, + "minipass": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.1.tgz", + "integrity": "sha512-UFqVihv6PQgwj8/yTGvl9kPz7xIAY+R5z6XYjRInD3Gk3qx6QGSD6zEcpeG4Dy/lQnv1J6zv8ejV90hyYIKf3w==", + "requires": { + "yallist": "^4.0.0" + } + }, + "minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-pipeline": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.2.tgz", + "integrity": "sha512-3JS5A2DKhD2g0Gg8x3yamO0pj7YeKGwVlDS90pF++kxptwx/F+B//roxf9SqYil5tQo65bijy+dAuAFZmYOouA==", + "requires": { + "minipass": "^3.0.0" + } + }, "mississippi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", @@ -9157,9 +10461,9 @@ } }, "node-releases": { - "version": "1.1.39", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.39.tgz", - "integrity": "sha512-8MRC/ErwNCHOlAFycy9OPca46fQYUjbJRDcZTHVWIGXIjYLM73k70vv3WkYutVnM4cCo4hE0MqBVVZjP6vjISA==", + "version": "1.1.42", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.42.tgz", + "integrity": "sha512-OQ/ESmUqGawI2PRX+XIRao44qWYBBfN54ImQYdWVTQqUckuejOg76ysSqDBK8NG3zwySRVnX36JwDQ6x+9GxzA==", "requires": { "semver": "^6.3.0" } @@ -9402,11 +10706,18 @@ } }, "open": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz", - "integrity": "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/open/-/open-7.0.0.tgz", + "integrity": "sha512-K6EKzYqnwQzk+/dzJAQSBORub3xlBTxMz+ntpZpH/LyCa1o6KjXhuN+2npAaI9jaSmU3R1Q8NWf4KUWcyytGsQ==", "requires": { - "is-wsl": "^1.1.0" + "is-wsl": "^2.1.0" + }, + "dependencies": { + "is-wsl": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.1.1.tgz", + "integrity": "sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog==" + } } }, "opn": { @@ -9523,15 +10834,26 @@ } }, "p-map": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "requires": { + "aggregate-error": "^3.0.0" + } }, "p-reduce": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=" }, + "p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", + "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", + "requires": { + "retry": "^0.12.0" + } + }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -9840,9 +11162,9 @@ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" }, "postcss": { - "version": "7.0.21", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.21.tgz", - "integrity": "sha512-uIFtJElxJo29QC753JzhidoAhvp/e/Exezkdhfmt8AymWT6/5B7W1WmponYWkHk2eg6sONyTch0A3nkMPun3SQ==", + "version": "7.0.24", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.24.tgz", + "integrity": "sha512-Xl0XvdNWg+CblAXzNvbSOUvgJXwSjmbAKORqyw9V2AlHrm1js2gFw9y3jibBAhpKZi8b5JzJCVh/FyzPsTtgTA==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -9891,11 +11213,11 @@ } }, "postcss-browser-comments": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-browser-comments/-/postcss-browser-comments-2.0.0.tgz", - "integrity": "sha512-xGG0UvoxwBc4Yx4JX3gc0RuDl1kc4bVihCzzk6UC72YPfq5fu3c717Nu8Un3nvnq1BJ31gBnFXIG/OaUTnpHgA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-browser-comments/-/postcss-browser-comments-3.0.0.tgz", + "integrity": "sha512-qfVjLfq7HFd2e0HW4s1dvU8X080OZdG46fFbIBFjW7US7YPDcWfRvdElvwMJr2LI6hMmD+7LnH2HcmXTs+uOig==", "requires": { - "postcss": "^7.0.2" + "postcss": "^7" } }, "postcss-calc": { @@ -10199,6 +11521,18 @@ "postcss": "^7.0.0", "postcss-load-config": "^2.0.0", "schema-utils": "^1.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } } }, "postcss-logical": { @@ -10318,30 +11652,38 @@ } }, "postcss-modules-local-by-default": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-2.0.6.tgz", - "integrity": "sha512-oLUV5YNkeIBa0yQl7EYnxMgy4N6noxmiwZStaEJUSe2xPMcdNc8WmBQuQCx18H5psYbVxz8zoHk0RAAYZXP9gA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.2.tgz", + "integrity": "sha512-jM/V8eqM4oJ/22j0gx4jrp63GSvDH6v86OqyTHHUvk4/k1vceipZsaymiZ5PvocqZOl5SFHiFJqjs3la0wnfIQ==", "requires": { - "postcss": "^7.0.6", - "postcss-selector-parser": "^6.0.0", - "postcss-value-parser": "^3.3.1" + "icss-utils": "^4.1.1", + "postcss": "^7.0.16", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.2.tgz", + "integrity": "sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ==" + } } }, "postcss-modules-scope": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.1.0.tgz", - "integrity": "sha512-91Rjps0JnmtUB0cujlc8KIKCsJXWjzuxGeT/+Q2i2HXKZ7nBUeF9YQTZZTNvHVoNYj1AthsjnGLtqDUE0Op79A==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.1.1.tgz", + "integrity": "sha512-OXRUPecnHCg8b9xWvldG/jUpRIGPNRka0r4D4j0ESUU2/5IOnpsjfPPmDprM3Ih8CgZ8FXjWqaniK5v4rWt3oQ==", "requires": { "postcss": "^7.0.6", "postcss-selector-parser": "^6.0.0" } }, "postcss-modules-values": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-2.0.0.tgz", - "integrity": "sha512-Ki7JZa7ff1N3EIMlPnGTZfUMe69FFwiQPnVSXC9mnn3jozCRBYIxiZd44yJOV2AmabOo4qFf8s0dC/+lweG7+w==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", + "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", "requires": { - "icss-replace-symbols": "^1.1.0", + "icss-utils": "^4.0.0", "postcss": "^7.0.6" } }, @@ -10354,14 +11696,15 @@ } }, "postcss-normalize": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize/-/postcss-normalize-7.0.1.tgz", - "integrity": "sha512-NOp1fwrG+6kVXWo7P9SizCHX6QvioxFD/hZcI2MLxPmVnFJFC0j0DDpIuNw2tUDeCFMni59gCVgeJ1/hYhj2OQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize/-/postcss-normalize-8.0.1.tgz", + "integrity": "sha512-rt9JMS/m9FHIRroDDBGSMsyW1c0fkvOJPy62ggxSHUldJO7B195TqFMqIf+lY5ezpDcYOV4j86aUp3/XbxzCCQ==", "requires": { - "@csstools/normalize.css": "^9.0.1", - "browserslist": "^4.1.1", - "postcss": "^7.0.2", - "postcss-browser-comments": "^2.0.0" + "@csstools/normalize.css": "^10.1.0", + "browserslist": "^4.6.2", + "postcss": "^7.0.17", + "postcss-browser-comments": "^3.0.0", + "sanitize.css": "^10.0.0" } }, "postcss-normalize-charset": { @@ -10915,33 +12258,33 @@ } }, "react-app-polyfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-1.0.4.tgz", - "integrity": "sha512-5Vte6ki7jpNsNCUKaboyofAhmURmCn2Y6Hu7ydJ6Iu4dct1CIGoh/1FT7gUZKAbowVX2lxVPlijvp1nKxfAl4w==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-1.0.5.tgz", + "integrity": "sha512-RcbV6+msbvZJZUIK/LX3UafPtoaDSJgUWu4sqBxHKTVmBsnlU2QWCKJRBRmgjxu+ivW/GPINbPWRM4Ppa6Lbgw==", "requires": { - "core-js": "3.2.1", - "object-assign": "4.1.1", - "promise": "8.0.3", - "raf": "3.4.1", - "regenerator-runtime": "0.13.3", - "whatwg-fetch": "3.0.0" + "core-js": "^3.4.1", + "object-assign": "^4.1.1", + "promise": "^8.0.3", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.3", + "whatwg-fetch": "^3.0.0" } }, "react-dev-utils": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-9.1.0.tgz", - "integrity": "sha512-X2KYF/lIGyGwP/F/oXgGDF24nxDA2KC4b7AFto+eqzc/t838gpSGiaU8trTqHXOohuLxxc5qi1eDzsl9ucPDpg==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-10.0.0.tgz", + "integrity": "sha512-8OKSJvl8ccXJDNf0YGw377L9v1OnT16skD/EuZWm0M/yr255etP4x4kuUCT1EfFfJ7Rhc4ZTpPTfPrvgiXa50Q==", "requires": { "@babel/code-frame": "7.5.5", "address": "1.1.2", - "browserslist": "4.7.0", + "browserslist": "4.7.3", "chalk": "2.4.2", "cross-spawn": "6.0.5", "detect-port-alt": "1.1.6", "escape-string-regexp": "1.0.5", "filesize": "3.6.1", "find-up": "3.0.0", - "fork-ts-checker-webpack-plugin": "1.5.0", + "fork-ts-checker-webpack-plugin": "3.1.0", "global-modules": "2.0.0", "globby": "8.0.2", "gzip-size": "5.1.1", @@ -10949,12 +12292,11 @@ "inquirer": "6.5.0", "is-root": "2.1.0", "loader-utils": "1.2.3", - "open": "^6.3.0", + "open": "^7.0.0", "pkg-up": "2.0.0", - "react-error-overlay": "^6.0.3", + "react-error-overlay": "^6.0.4", "recursive-readdir": "2.2.2", "shell-quote": "1.7.2", - "sockjs-client": "1.4.0", "strip-ansi": "5.2.0", "text-table": "0.2.0" }, @@ -10970,13 +12312,13 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" }, "browserslist": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.7.0.tgz", - "integrity": "sha512-9rGNDtnj+HaahxiVV38Gn8n8Lr8REKsel68v1sPFfIGEK6uSXTY3h9acgiT1dZVtOOUtifo/Dn8daDQ5dUgVsA==", + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.7.3.tgz", + "integrity": "sha512-jWvmhqYpx+9EZm/FxcZSbUZyDEvDTLDi3nSAKbzEkyWvtI0mNSmUosey+5awDW1RUlrgXbQb5A6qY1xQH9U6MQ==", "requires": { - "caniuse-lite": "^1.0.30000989", - "electron-to-chromium": "^1.3.247", - "node-releases": "^1.1.29" + "caniuse-lite": "^1.0.30001010", + "electron-to-chromium": "^1.3.306", + "node-releases": "^1.1.40" } }, "cli-cursor": { @@ -11080,9 +12422,9 @@ } }, "react-error-overlay": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.3.tgz", - "integrity": "sha512-bOUvMWFQVk5oz8Ded9Xb7WVdEi3QGLC8tH7HmYP0Fdp4Bn3qw0tRFmr5TW6mvahzvmrK4a6bqWGfCevBflP+Xw==" + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.4.tgz", + "integrity": "sha512-ueZzLmHltszTshDMwyfELDq8zOA803wQ1ZuzCccXa1m57k1PxSHfflPD5W9YIiTXLs0JTLzoj6o1LuM5N6zzNA==" }, "react-is": { "version": "16.11.0", @@ -11136,70 +12478,188 @@ } }, "react-scripts": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-3.2.0.tgz", - "integrity": "sha512-6LzuKbE2B4eFQG6i1FnTScn9HDcWBfXXnOwW9xKFPJ/E3rK8i1ufbOZ0ocKyRPxJAKdN7iqg3i7lt0+oxkSVOA==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-3.3.0.tgz", + "integrity": "sha512-hzPc6bxCc9GnsspWqk494c2Gpd0dRbk/C8q76BNQIENi9GMwoxFljOEcZoZcpFpJgQ45alxFR6QaLt+51qie7g==", "requires": { - "@babel/core": "7.6.0", - "@svgr/webpack": "4.3.2", - "@typescript-eslint/eslint-plugin": "^2.2.0", - "@typescript-eslint/parser": "^2.2.0", + "@babel/core": "7.7.4", + "@svgr/webpack": "4.3.3", + "@typescript-eslint/eslint-plugin": "^2.8.0", + "@typescript-eslint/parser": "^2.8.0", "babel-eslint": "10.0.3", "babel-jest": "^24.9.0", "babel-loader": "8.0.6", - "babel-plugin-named-asset-import": "^0.3.4", - "babel-preset-react-app": "^9.0.2", - "camelcase": "^5.2.0", + "babel-plugin-named-asset-import": "^0.3.5", + "babel-preset-react-app": "^9.1.0", + "camelcase": "^5.3.1", "case-sensitive-paths-webpack-plugin": "2.2.0", - "css-loader": "2.1.1", - "dotenv": "6.2.0", + "css-loader": "3.2.0", + "dotenv": "8.2.0", "dotenv-expand": "5.1.0", - "eslint": "^6.1.0", - "eslint-config-react-app": "^5.0.2", + "eslint": "^6.6.0", + "eslint-config-react-app": "^5.1.0", "eslint-loader": "3.0.2", "eslint-plugin-flowtype": "3.13.0", "eslint-plugin-import": "2.18.2", "eslint-plugin-jsx-a11y": "6.2.3", - "eslint-plugin-react": "7.14.3", + "eslint-plugin-react": "7.16.0", "eslint-plugin-react-hooks": "^1.6.1", - "file-loader": "3.0.1", - "fs-extra": "7.0.1", - "fsevents": "2.0.7", + "file-loader": "4.3.0", + "fs-extra": "^8.1.0", + "fsevents": "2.1.2", "html-webpack-plugin": "4.0.0-beta.5", "identity-obj-proxy": "3.0.0", - "is-wsl": "^1.1.0", "jest": "24.9.0", "jest-environment-jsdom-fourteen": "0.1.0", "jest-resolve": "24.9.0", - "jest-watch-typeahead": "0.4.0", + "jest-watch-typeahead": "0.4.2", "mini-css-extract-plugin": "0.8.0", "optimize-css-assets-webpack-plugin": "5.0.3", "pnp-webpack-plugin": "1.5.0", "postcss-flexbugs-fixes": "4.1.0", "postcss-loader": "3.0.0", - "postcss-normalize": "7.0.1", + "postcss-normalize": "8.0.1", "postcss-preset-env": "6.7.0", "postcss-safe-parser": "4.0.1", - "react-app-polyfill": "^1.0.4", - "react-dev-utils": "^9.1.0", - "resolve": "1.12.0", - "resolve-url-loader": "3.1.0", - "sass-loader": "7.2.0", + "react-app-polyfill": "^1.0.5", + "react-dev-utils": "^10.0.0", + "resolve": "1.12.2", + "resolve-url-loader": "3.1.1", + "sass-loader": "8.0.0", "semver": "6.3.0", "style-loader": "1.0.0", - "terser-webpack-plugin": "1.4.1", - "ts-pnp": "1.1.4", - "url-loader": "2.1.0", - "webpack": "4.41.0", - "webpack-dev-server": "3.2.1", - "webpack-manifest-plugin": "2.1.1", + "terser-webpack-plugin": "2.2.1", + "ts-pnp": "1.1.5", + "url-loader": "2.3.0", + "webpack": "4.41.2", + "webpack-dev-server": "3.9.0", + "webpack-manifest-plugin": "2.2.0", "workbox-webpack-plugin": "4.3.1" }, "dependencies": { - "dotenv": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz", - "integrity": "sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w==" + "@babel/core": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.4.tgz", + "integrity": "sha512-+bYbx56j4nYBmpsWtnPUsKW3NdnYxbqyfrP2w9wILBuHzdfIKz9prieZK0DFPyIzkjYVUe4QkusGL07r5pXznQ==", + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.7.4", + "@babel/helpers": "^7.7.4", + "@babel/parser": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@babel/types": "^7.7.4", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "json5": "^2.1.0", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "@babel/generator": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.4.tgz", + "integrity": "sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg==", + "requires": { + "@babel/types": "^7.7.4", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + } + }, + "@babel/helper-function-name": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz", + "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==", + "requires": { + "@babel/helper-get-function-arity": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz", + "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz", + "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==", + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/helpers": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.7.4.tgz", + "integrity": "sha512-ak5NGZGJ6LV85Q1Zc9gn2n+ayXOizryhjSUBTdu5ih1tlVCJeuQENzc4ItyCVhINVXvIT/ZQ4mheGIsfBkpskg==", + "requires": { + "@babel/template": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/parser": { + "version": "7.7.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.5.tgz", + "integrity": "sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig==" + }, + "@babel/template": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz", + "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/traverse": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz", + "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==", + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.7.4", + "@babel/helper-function-name": "^7.7.4", + "@babel/helper-split-export-declaration": "^7.7.4", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } + }, + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "resolve": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.2.tgz", + "integrity": "sha512-cAVTI2VLHWYsGOirfeYVVQ7ZDejtQ9fp4YhYckWDEkFfqbVjaT11iM8k6xSAfGFMM+gDpZjMnFssPu8we+mqFw==", + "requires": { + "path-parse": "^1.0.6" + } } } }, @@ -11331,9 +12791,9 @@ } }, "regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.0.0.tgz", + "integrity": "sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g==" }, "regexpu-core": { "version": "4.6.0", @@ -11548,39 +13008,26 @@ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" }, "resolve-url-loader": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-3.1.0.tgz", - "integrity": "sha512-2QcrA+2QgVqsMJ1Hn5NnJXIGCX1clQ1F6QJTqOeiaDw9ACo1G2k+8/shq3mtqne03HOFyskAClqfxKyFBriXZg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-3.1.1.tgz", + "integrity": "sha512-K1N5xUjj7v0l2j/3Sgs5b8CjrrgtC70SmdCuZiJ8tSyb5J+uk3FoeZ4b7yTnH6j7ngI+Bc5bldHJIa8hYdu2gQ==", "requires": { "adjust-sourcemap-loader": "2.0.0", - "camelcase": "5.0.0", + "camelcase": "5.3.1", "compose-function": "3.0.3", - "convert-source-map": "1.6.0", + "convert-source-map": "1.7.0", "es6-iterator": "2.0.3", "loader-utils": "1.2.3", - "postcss": "7.0.14", + "postcss": "7.0.21", "rework": "1.0.1", "rework-visit": "1.0.0", "source-map": "0.6.1" }, "dependencies": { - "camelcase": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", - "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==" - }, - "convert-source-map": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", - "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", - "requires": { - "safe-buffer": "~5.1.1" - } - }, "postcss": { - "version": "7.0.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", - "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", + "version": "7.0.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.21.tgz", + "integrity": "sha512-uIFtJElxJo29QC753JzhidoAhvp/e/Exezkdhfmt8AymWT6/5B7W1WmponYWkHk2eg6sONyTch0A3nkMPun3SQ==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -11616,6 +13063,11 @@ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=" + }, "rework": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/rework/-/rework-1.0.1.tgz", @@ -11727,16 +13179,21 @@ "walker": "~1.0.5" } }, + "sanitize.css": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-10.0.0.tgz", + "integrity": "sha512-vTxrZz4dX5W86M6oVWVdOVe72ZiPs41Oi7Z6Km4W5Turyz28mrXSJhhEBZoRtzJWIv3833WKVwLSDWWkEfupMg==" + }, "sass-loader": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.2.0.tgz", - "integrity": "sha512-h8yUWaWtsbuIiOCgR9fd9c2lRXZ2uG+h8Dzg/AGNj+Hg/3TO8+BBAW9mEP+mh8ei+qBKqSJ0F1FLlYjNBc61OA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-8.0.0.tgz", + "integrity": "sha512-+qeMu563PN7rPdit2+n5uuYVR0SSVwm0JsOUsaJXzgYcClWSlmX0iHDnmeOobPkf5kUglVot3QS6SyLyaQoJ4w==", "requires": { "clone-deep": "^4.0.1", - "loader-utils": "^1.0.1", - "neo-async": "^2.5.0", - "pify": "^4.0.1", - "semver": "^5.5.0" + "loader-utils": "^1.2.3", + "neo-async": "^2.6.1", + "schema-utils": "^2.1.0", + "semver": "^6.3.0" }, "dependencies": { "clone-deep": { @@ -11754,16 +13211,6 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - }, "shallow-clone": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", @@ -11797,13 +13244,12 @@ } }, "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.1.tgz", + "integrity": "sha512-0WXHDs1VDJyo+Zqs9TKLKyD/h7yDpHUhEFsM2CzkICFdoX1av+GBq/J2xRTFfsQO5kBfhZzANf2VcIm84jqDbg==", "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1" } }, "select-hose": { @@ -11872,9 +13318,9 @@ } }, "serialize-javascript": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz", - "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.1.tgz", + "integrity": "sha512-MPLPRpD4FNqWq9tTIjYG5LesFouDhdyH0EPY3gVK4DRD5+g4aDqdNSzLIwceulo3Yj+PL1bPh6laE5+H6LTcrQ==" }, "serve-index": { "version": "1.9.1", @@ -12299,16 +13745,6 @@ "requires": { "faye-websocket": "^0.10.0", "uuid": "^3.0.1" - }, - "dependencies": { - "faye-websocket": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", - "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "requires": { - "websocket-driver": ">=0.5.1" - } - } } }, "sockjs-client": { @@ -12331,6 +13767,14 @@ "requires": { "ms": "^2.1.1" } + }, + "faye-websocket": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", + "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", + "requires": { + "websocket-driver": ">=0.5.1" + } } } }, @@ -12468,11 +13912,12 @@ } }, "ssri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-7.1.0.tgz", + "integrity": "sha512-77/WrDZUWocK0mvA5NTRQyveUf+wsrIc6vyrxpS8tVvYBcX215QbafrJR3KtkpskIzoFLqqNuuYQvxaMjXJ/0g==", "requires": { - "figgy-pudding": "^3.5.1" + "figgy-pudding": "^3.5.1", + "minipass": "^3.1.1" } }, "stable": { @@ -12627,13 +14072,28 @@ } }, "string-width": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.1.0.tgz", - "integrity": "sha512-NrX+1dVVh+6Y9dnQ19pR0pP4FiEIlUvdTGn8pw6CKTNq5sgib2nIhmUNT5TAmhWmvKr3WcxBcP3E8nWezuipuQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^5.2.0" + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + } } }, "string.prototype.trimleft": { @@ -12718,17 +14178,6 @@ "requires": { "loader-utils": "^1.2.3", "schema-utils": "^2.0.1" - }, - "dependencies": { - "schema-utils": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.5.0.tgz", - "integrity": "sha512-32ISrwW2scPXHUSusP8qMg5dLUawKkyV+/qIEV9JdXKx+rsM6mi8vZY8khg2M69Qom16rtroWXD3Ybtiws38gQ==", - "requires": { - "ajv": "^6.10.2", - "ajv-keywords": "^3.4.1" - } - } } }, "styled-components": { @@ -12860,9 +14309,9 @@ "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" }, "terser": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.4.0.tgz", - "integrity": "sha512-oDG16n2WKm27JO8h4y/w3iqBGAOSCtq7k8dRmrn4Wf9NouL0b2WpMHGChFGZq4nFAQy1FsNJrVQHfurXOSTmOA==", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.4.2.tgz", + "integrity": "sha512-Uufrsvhj9O1ikwgITGsZ5EZS6qPokUOkCegS7fYOdGTv+OA90vndUbU6PEjr5ePqHfNUbGyMO7xyIZv2MhsALQ==", "requires": { "commander": "^2.20.0", "source-map": "~0.6.1", @@ -12877,21 +14326,76 @@ } }, "terser-webpack-plugin": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.1.tgz", - "integrity": "sha512-ZXmmfiwtCLfz8WKZyYUuuHf3dMYEjg8NrjHMb0JqHVHVOSkzp3cW2/XG1fP3tRhqEqSzMwzzRQGtAPbs4Cncxg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.2.1.tgz", + "integrity": "sha512-jwdauV5Al7zopR6OAYvIIRcxXCSvLjZjr7uZE8l2tIWb/ryrGN48sJftqGf5k9z09tWhajx53ldp0XPI080YnA==", "requires": { - "cacache": "^12.0.2", - "find-cache-dir": "^2.1.0", - "is-wsl": "^1.1.0", - "schema-utils": "^1.0.0", - "serialize-javascript": "^1.7.0", + "cacache": "^13.0.1", + "find-cache-dir": "^3.0.0", + "jest-worker": "^24.9.0", + "schema-utils": "^2.5.0", + "serialize-javascript": "^2.1.0", "source-map": "^0.6.1", - "terser": "^4.1.2", - "webpack-sources": "^1.4.0", - "worker-farm": "^1.7.0" + "terser": "^4.3.9", + "webpack-sources": "^1.4.3" }, "dependencies": { + "find-cache-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.1.0.tgz", + "integrity": "sha512-zw+EFiNBNPgI2NTrKkDd1xd7q0cs6wr/iWnr/oUkI0yF9K9GqQ+riIt4aiyFaaqpaWbxPrJXHI+QvmNUQbX+0Q==", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.0", + "pkg-dir": "^4.1.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "make-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz", + "integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==", + "requires": { + "semver": "^6.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==", + "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==" + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "requires": { + "find-up": "^4.0.0" + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -13107,9 +14611,9 @@ } }, "ts-pnp": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.1.4.tgz", - "integrity": "sha512-1J/vefLC+BWSo+qe8OnJQfWTYRS6ingxjwqmHMqaMxXMj7kFtKLgAaYW3JeX3mktjgUL+etlU8/B4VUAUI9QGw==" + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.1.5.tgz", + "integrity": "sha512-ti7OGMOUOzo66wLF3liskw6YQIaSsBgc4GOAlWRnIEj8htCxJUxskanMUoJOD6MDCRAXo36goXJZch+nOS0VMA==" }, "tslib": { "version": "1.10.0", @@ -13156,9 +14660,9 @@ } }, "type-fest": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.5.2.tgz", - "integrity": "sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw==" + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" }, "type-is": { "version": "1.6.18", @@ -13352,24 +14856,13 @@ } }, "url-loader": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-2.1.0.tgz", - "integrity": "sha512-kVrp/8VfEm5fUt+fl2E0FQyrpmOYgMEkBsv8+UDP1wFhszECq5JyGF33I7cajlVY90zRZ6MyfgKXngLvHYZX8A==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-2.3.0.tgz", + "integrity": "sha512-goSdg8VY+7nPZKUEChZSEtW5gjbS66USIGCeSJ1OVOJ7Yfuh/36YxCwMi5HVEJh6mqUYOoy3NJ0vlOMrWsSHog==", "requires": { "loader-utils": "^1.2.3", "mime": "^2.4.4", - "schema-utils": "^2.0.0" - }, - "dependencies": { - "schema-utils": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.5.0.tgz", - "integrity": "sha512-32ISrwW2scPXHUSusP8qMg5dLUawKkyV+/qIEV9JdXKx+rsM6mi8vZY8khg2M69Qom16rtroWXD3Ybtiws38gQ==", - "requires": { - "ajv": "^6.10.2", - "ajv-keywords": "^3.4.1" - } - } + "schema-utils": "^2.5.0" } }, "url-parse": { @@ -13524,9 +15017,9 @@ "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" }, "webpack": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.0.tgz", - "integrity": "sha512-yNV98U4r7wX1VJAj5kyMsu36T8RPPQntcb5fJLOsMz/pt/WrKC0Vp1bAlqPLkA1LegSwQwf6P+kAbyhRKVQ72g==", + "version": "4.41.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.2.tgz", + "integrity": "sha512-Zhw69edTGfbz9/8JJoyRQ/pq8FYUoY0diOXqW0T6yhgdhCv6wr0hra5DwwWexNRns2Z2+gsnrNcbe9hbGBgk/A==", "requires": { "@webassemblyjs/ast": "1.8.5", "@webassemblyjs/helper-module-context": "1.8.5", @@ -13554,9 +15047,31 @@ }, "dependencies": { "acorn": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz", - "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==" + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", + "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==" + }, + "cacache": { + "version": "12.0.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz", + "integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==", + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } }, "eslint-scope": { "version": "4.0.3", @@ -13566,6 +15081,50 @@ "esrecurse": "^4.1.0", "estraverse": "^4.1.1" } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "serialize-javascript": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", + "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "terser-webpack-plugin": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz", + "integrity": "sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA==", + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^2.1.2", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + } } } }, @@ -13582,40 +15141,43 @@ } }, "webpack-dev-server": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.2.1.tgz", - "integrity": "sha512-sjuE4mnmx6JOh9kvSbPYw3u/6uxCLHNWfhWaIPwcXWsvWOPN+nc5baq4i9jui3oOBRXGonK9+OI0jVkaz6/rCw==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.9.0.tgz", + "integrity": "sha512-E6uQ4kRrTX9URN9s/lIbqTAztwEPdvzVrcmHE8EQ9YnuT9J8Es5Wrd8n9BKg1a0oZ5EgEke/EQFgUsp18dSTBw==", "requires": { "ansi-html": "0.0.7", "bonjour": "^3.5.0", - "chokidar": "^2.0.0", - "compression": "^1.5.2", - "connect-history-api-fallback": "^1.3.0", + "chokidar": "^2.1.8", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", "debug": "^4.1.1", - "del": "^3.0.0", - "express": "^4.16.2", - "html-entities": "^1.2.0", - "http-proxy-middleware": "^0.19.1", + "del": "^4.1.1", + "express": "^4.17.1", + "html-entities": "^1.2.1", + "http-proxy-middleware": "0.19.1", "import-local": "^2.0.0", - "internal-ip": "^4.2.0", + "internal-ip": "^4.3.0", "ip": "^1.1.5", - "killable": "^1.0.0", - "loglevel": "^1.4.1", - "opn": "^5.1.0", - "portfinder": "^1.0.9", + "is-absolute-url": "^3.0.3", + "killable": "^1.0.1", + "loglevel": "^1.6.4", + "opn": "^5.5.0", + "p-retry": "^3.0.1", + "portfinder": "^1.0.25", "schema-utils": "^1.0.0", - "selfsigned": "^1.9.1", - "semver": "^5.6.0", - "serve-index": "^1.7.2", + "selfsigned": "^1.10.7", + "semver": "^6.3.0", + "serve-index": "^1.9.1", "sockjs": "0.3.19", - "sockjs-client": "1.3.0", - "spdy": "^4.0.0", - "strip-ansi": "^3.0.0", + "sockjs-client": "1.4.0", + "spdy": "^4.0.1", + "strip-ansi": "^3.0.1", "supports-color": "^6.1.0", "url": "^0.11.0", - "webpack-dev-middleware": "^3.5.1", + "webpack-dev-middleware": "^3.7.2", "webpack-log": "^2.0.0", - "yargs": "12.0.2" + "ws": "^6.2.1", + "yargs": "12.0.5" }, "dependencies": { "ansi-regex": { @@ -13623,11 +15185,6 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" - }, "cliui": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", @@ -13653,19 +15210,16 @@ } } }, - "decamelize": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz", - "integrity": "sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==", - "requires": { - "xregexp": "4.0.0" - } - }, "get-caller-file": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" }, + "is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==" + }, "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", @@ -13676,32 +15230,14 @@ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - }, - "sockjs-client": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.3.0.tgz", - "integrity": "sha512-R9jxEzhnnrdxLCNln0xg5uGHqMnkhPSTzUZH2eXcR03S/On9Yvoq2wyUZILRUhZCNVu2PmwWVoyuiPz8th8zbg==", - "requires": { - "debug": "^3.2.5", - "eventsource": "^1.0.7", - "faye-websocket": "~0.11.1", - "inherits": "^2.0.3", - "json3": "^3.3.2", - "url-parse": "^1.4.3" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - } + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" } }, "string-width": { @@ -13773,13 +15309,21 @@ } } }, + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "requires": { + "async-limiter": "~1.0.0" + } + }, "yargs": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.2.tgz", - "integrity": "sha512-e7SkEx6N6SIZ5c5H22RTZae61qtn3PYUE8JYbBFlK9sYmh3DMQ6E5ygtaG/2BW0JZi4WGgTR2IV5ChqlqrDGVQ==", + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", "requires": { "cliui": "^4.0.0", - "decamelize": "^2.0.0", + "decamelize": "^1.2.0", "find-up": "^3.0.0", "get-caller-file": "^1.0.1", "os-locale": "^3.0.0", @@ -13789,15 +15333,16 @@ "string-width": "^2.0.0", "which-module": "^2.0.0", "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^10.1.0" + "yargs-parser": "^11.1.1" } }, "yargs-parser": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", - "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", "requires": { - "camelcase": "^4.1.0" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } @@ -13812,14 +15357,26 @@ } }, "webpack-manifest-plugin": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/webpack-manifest-plugin/-/webpack-manifest-plugin-2.1.1.tgz", - "integrity": "sha512-2zqJ6mvc3yoiqfDjghAIpljhLSDh/G7vqGrzYcYqqRCd/ZZZCAuc/YPE5xG0LGpLgDJRhUNV1H+znyyhIxahzA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/webpack-manifest-plugin/-/webpack-manifest-plugin-2.2.0.tgz", + "integrity": "sha512-9S6YyKKKh/Oz/eryM1RyLVDVmy3NSPV0JXMRhZ18fJsq+AwGxUY34X54VNwkzYcEmEkDwNxuEOboCZEebJXBAQ==", "requires": { "fs-extra": "^7.0.0", "lodash": ">=3.5 <5", "object.entries": "^1.1.0", "tapable": "^1.0.0" + }, + "dependencies": { + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + } } }, "webpack-sources": { @@ -14160,11 +15717,6 @@ "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", "dev": true }, - "xregexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", - "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==" - }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -14176,9 +15728,27 @@ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" }, "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "yaml": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.7.2.tgz", + "integrity": "sha512-qXROVp90sb83XtAoqE8bP9RwAkTTZbugRUTm5YeFCBfNRPEp2YzTeqWiz7m5OORHzEvrA/qcGS8hp/E+MMROYw==", + "requires": { + "@babel/runtime": "^7.6.3" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.7.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.6.tgz", + "integrity": "sha512-BWAJxpNVa0QlE5gZdWjSxXtemZyZ9RmrmVozxt3NUXeZhVIJ5ANyqmMc0JDrivBZyxUuQvFxlvH4OWWOogGfUw==", + "requires": { + "regenerator-runtime": "^0.13.2" + } + } + } }, "yargs": { "version": "13.3.0", diff --git a/client/package.json b/client/package.json index ef7f5ac3..e16c9a80 100644 --- a/client/package.json +++ b/client/package.json @@ -4,15 +4,18 @@ "private": true, "proxy": "http://localhost:3001", "dependencies": { + "@types/jsonwebtoken": "^8.3.5", "@types/node": "12.12.7", "@types/react": "16.9.11", "@types/react-dom": "16.9.4", "@types/styled-components": "^4.4.0", "axios": "^0.19.0", + "jsonwebtoken": "^8.5.1", "react": "^16.11.0", "react-dom": "^16.11.0", "react-router-dom": "^5.1.2", - "react-scripts": "3.2.0", + "react-scripts": "^3.3.0", + "serialize-javascript": "^2.1.1", "styled-components": "^4.4.1", "typescript": "3.7.2" }, diff --git a/client/src/@context/http-providers/http-providers.tsx b/client/src/@context/http-providers/http-providers.tsx index 24fde7b7..25c777f5 100644 --- a/client/src/@context/http-providers/http-providers.tsx +++ b/client/src/@context/http-providers/http-providers.tsx @@ -1,16 +1,31 @@ -import { ChannelApi } from "data/http/api/channel-api"; import { AxiosWrapper } from "data/http/api/axios-wrapper"; +import { ChannelApi } from "data/http/api/channel-api"; import { PostApi } from "data/http/api/post-api"; +import { SnugApi } from "data/http/api/snug-api"; +import { UserApi } from "data/http/api/user-api"; +import { AuthApi } from "data/http/api/auth-api"; +import { InviteApi } from "data/http/api/invite-api"; +import { ProfileApi } from "data/http/api/profile-api"; export class HttpProviderDependencies { private readonly channel: ChannelApi; private readonly post: PostApi; + private readonly snug: SnugApi; + private readonly auth: AuthApi; + private readonly user: UserApi; + private readonly invite: InviteApi; + private readonly profile: ProfileApi; private readonly axiosWrapper: AxiosWrapper; constructor() { this.axiosWrapper = new AxiosWrapper(); this.channel = new ChannelApi(this.axiosWrapper); this.post = new PostApi(this.axiosWrapper); + this.snug = new SnugApi(this.axiosWrapper); + this.auth = new AuthApi(this.axiosWrapper); + this.user = new UserApi(this.axiosWrapper); + this.invite = new InviteApi(this.axiosWrapper); + this.profile = new ProfileApi(this.axiosWrapper); } getChannel(): ChannelApi { @@ -20,4 +35,24 @@ export class HttpProviderDependencies { getPost(): PostApi { return this.post; } + + getSnug(): SnugApi { + return this.snug; + } + + getAuth(): AuthApi { + return this.auth; + } + + getUser(): UserApi { + return this.user; + } + + getInvite(): InviteApi { + return this.invite; + } + + getProfile(): ProfileApi { + return this.profile; + } } diff --git a/client/src/@context/repositories/index.tsx b/client/src/@context/repositories/index.tsx index 8cb92a0c..c7b9ba6a 100644 --- a/client/src/@context/repositories/index.tsx +++ b/client/src/@context/repositories/index.tsx @@ -2,10 +2,21 @@ import { StorageProviderDependencies } from "@context/storage-providers/storage- import { HttpProviderDependencies } from "@context/http-providers/http-providers"; import { ChatRoomRepositoryDependency } from "./chat-room"; import { PostingRepositoryDependency } from "./posting"; +import { SnugRepositoryDependency } from "./snug"; +import { AuthRepository } from "data/repository/auth-repository"; +import { UserRepositoryDependency } from "./user"; +import { InviteRepositoryDependency } from "./invite"; +import { ProfileRepositoryDependency } from "./profile"; export class RepositoryDependencies { private readonly chatRoom: ChatRoomRepositoryDependency; private readonly posting: PostingRepositoryDependency; + private readonly snug: SnugRepositoryDependency; + private readonly invite: InviteRepositoryDependency; + + private readonly auth: AuthRepository; + private readonly user: UserRepositoryDependency; + private readonly profile: ProfileRepositoryDependency; constructor( apies: HttpProviderDependencies, @@ -13,6 +24,11 @@ export class RepositoryDependencies { ) { this.chatRoom = new ChatRoomRepositoryDependency(apies.getChannel()); this.posting = new PostingRepositoryDependency(apies.getPost()); + this.snug = new SnugRepositoryDependency(apies.getSnug()); + this.invite = new InviteRepositoryDependency(apies.getInvite()); + this.auth = new AuthRepository(apies.getAuth(), storage.getJwtLocal()); + this.user = new UserRepositoryDependency(apies.getUser()); + this.profile = new ProfileRepositoryDependency(apies.getProfile()); } getChatRoom() { @@ -22,4 +38,23 @@ export class RepositoryDependencies { getPosting() { return this.posting; } + + getSnug() { + return this.snug; + } + getAuth() { + return this.auth; + } + + getUser() { + return this.user; + } + + getInvite() { + return this.invite; + } + + getProfile() { + return this.profile; + } } diff --git a/client/src/@context/repositories/invite.ts b/client/src/@context/repositories/invite.ts new file mode 100644 index 00000000..d374eaee --- /dev/null +++ b/client/src/@context/repositories/invite.ts @@ -0,0 +1,15 @@ +import {InviteRepositoryType} from "core/use-case/invite-repository-type"; +import {InviteApi} from "data/http/api/invite-api"; +import {InviteRepository} from "data/repository/invite-repository"; + +export class InviteRepositoryDependency { + private readonly inviteRepository: InviteRepositoryType; + + constructor(api: InviteApi) { + this.inviteRepository = new InviteRepository(api); + } + + getInviteRepository(): InviteRepositoryType { + return this.inviteRepository; + } +} diff --git a/client/src/@context/repositories/profile.ts b/client/src/@context/repositories/profile.ts new file mode 100644 index 00000000..2fbb9c8b --- /dev/null +++ b/client/src/@context/repositories/profile.ts @@ -0,0 +1,15 @@ +import { ProfileApi } from "data/http/api/profile-api"; +import { ProfileRepository } from "data/repository/profile-repository"; +import { ProfileRepositoryType } from "core/use-case/profile-repository-type"; + +export class ProfileRepositoryDependency { + private readonly profileRepository: ProfileRepositoryType; + + constructor(api: ProfileApi) { + this.profileRepository = new ProfileRepository(api); + } + + getProfileRepository(): ProfileRepositoryType { + return this.profileRepository; + } +} diff --git a/client/src/@context/repositories/snug.ts b/client/src/@context/repositories/snug.ts new file mode 100644 index 00000000..634dafbf --- /dev/null +++ b/client/src/@context/repositories/snug.ts @@ -0,0 +1,15 @@ +import { SnugApi } from "data/http/api/snug-api"; +import { SnugRepository } from "data/repository/snug-repository"; +import { SnugRepositoryType } from "core/use-case/snug-repository-type"; + +export class SnugRepositoryDependency { + private readonly postRepository: SnugRepositoryType; + + constructor(api: SnugApi) { + this.postRepository = new SnugRepository(api); + } + + getSnugRepository(): SnugRepositoryType { + return this.postRepository; + } +} diff --git a/client/src/@context/repositories/user.ts b/client/src/@context/repositories/user.ts new file mode 100644 index 00000000..434683a6 --- /dev/null +++ b/client/src/@context/repositories/user.ts @@ -0,0 +1,15 @@ +import { UserApi } from "data/http/api/user-api"; +import { UserRepositoryType } from "core/use-case/user-repository-type"; +import { UserRepository } from "data/repository/user-repository"; + +export class UserRepositoryDependency { + private readonly userRepository: UserRepositoryType; + + constructor(api: UserApi) { + this.userRepository = new UserRepository(api); + } + + getUserRepository(): UserRepositoryType { + return this.userRepository; + } +} diff --git a/client/src/@context/services/index.tsx b/client/src/@context/services/index.tsx index 66ede504..42e6bf31 100644 --- a/client/src/@context/services/index.tsx +++ b/client/src/@context/services/index.tsx @@ -1,10 +1,20 @@ import { RepositoryDependencies } from "@context/repositories/index"; import { ChannelService } from "core/service/channel-service"; import { PostService } from "core/service/post-service"; +import { SnugService } from "core/service/snug-service"; +import { AuthService } from "core/service/auth-service"; +import { UserService } from "core/service/user-service"; +import { InviteService } from "core/service/invite-service"; +import { ProfileService } from "core/service/profile-service"; export class ServiceDependencies { readonly channelService: ChannelService; + readonly userService: UserService; readonly postService: PostService; + readonly snugService: SnugService; + readonly authService: AuthService; + readonly inviteService: InviteService; + readonly profileService: ProfileService; constructor(repositories: RepositoryDependencies) { this.channelService = new ChannelService( @@ -13,5 +23,18 @@ export class ServiceDependencies { this.postService = new PostService( repositories.getPosting().getPostRepository() ); + this.snugService = new SnugService( + repositories.getSnug().getSnugRepository() + ); + this.authService = new AuthService(repositories.getAuth()); + this.userService = new UserService( + repositories.getUser().getUserRepository() + ); + this.inviteService = new InviteService( + repositories.getInvite().getInviteRepository() + ); + this.profileService = new ProfileService( + repositories.getProfile().getProfileRepository() + ); } } diff --git a/client/src/@context/storage-providers/storage-providers.tsx b/client/src/@context/storage-providers/storage-providers.tsx index 7af88f24..b529ea37 100644 --- a/client/src/@context/storage-providers/storage-providers.tsx +++ b/client/src/@context/storage-providers/storage-providers.tsx @@ -1,3 +1,20 @@ +import { BrowserStorage } from "data/browser-storage/browser-storage"; +import { JsonWebToken } from "core/model/json-web-token-model"; +import { JsonWebTokenMapper } from "data/browser-storage/custom-mapper/json-web-tocken-mapper"; +import { StorageType } from "data/browser-storage/browser-storage-helper"; + export class StorageProviderDependencies { - constructor() {} + private readonly jwtLocal: BrowserStorage; + + constructor() { + this.jwtLocal = new BrowserStorage( + "jwt", + new JsonWebTokenMapper(), + StorageType.LOCAL + ); + } + + getJwtLocal(): BrowserStorage { + return this.jwtLocal; + } } diff --git a/client/src/App.tsx b/client/src/App.tsx index e7c7cc80..46f65ccc 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,68 +1,89 @@ -import React, { useEffect } from "react"; +import React from "react"; import { Route, BrowserRouter } from "react-router-dom"; -import { createBrowserHistory } from "history"; import { Home } from "./presentation/pages/home/index"; import { Snug } from "./presentation/pages/snug/index"; -import { RegisterSnug } from "./presentation/pages/register-snug/index"; +import { RegisterSnug } from "./presentation/pages/register-snug"; import { RegisterUser } from "./presentation/pages/register-user/index"; +import { InviteUsers } from "presentation/pages/invite-users"; import { Application } from "./context.instance"; import { createGlobalStyle } from "styled-components"; -import socketIO from "socket.io-client"; import dotenv from "dotenv"; +import { PathParameterContextProvider } from "contexts/path-parameter-context"; +import { ApplicationContextProvider } from "contexts/application-context"; +import { SocketContextProvider } from "contexts/socket-context"; dotenv.config(); + const GlobalStyle = createGlobalStyle` + @import url(https://fonts.googleapis.com/css?family=Nanum+Gothic:regular,700,800); body{ padding: 0; margin: 0; + font-family: "Nanum Gothic",sans-serif; } #root{ width:100vw; height:100vh; } + a { + text-decoration: none; + } `; + const App: React.FC = () => { - const history = createBrowserHistory(); - const socket = socketIO(process.env.REACT_APP_SOCKET_SERVER_HOST!); return ( - - - ( - - )} - > - ( - - )} - > - ( - - )} - > - ( - - )} - /> - ( - - )} - > - + + + + + + ( + + )} + > + ( + + )} + > + ( + + )} + > + ( + + )} + > + ( + + )} + > + ( + + )} + > + + + + ); }; + export default App; diff --git a/client/src/assets/gipyoo.png b/client/src/assets/gipyoo.png new file mode 100644 index 00000000..dccbd831 Binary files /dev/null and b/client/src/assets/gipyoo.png differ diff --git a/client/src/assets/left-arrow.png b/client/src/assets/left-arrow.png new file mode 100644 index 00000000..75ea3747 Binary files /dev/null and b/client/src/assets/left-arrow.png differ diff --git a/client/src/assets/more.png b/client/src/assets/more.png new file mode 100644 index 00000000..1a067723 Binary files /dev/null and b/client/src/assets/more.png differ diff --git a/client/src/assets/right-arrow.png b/client/src/assets/right-arrow.png new file mode 100644 index 00000000..3e5a60d1 Binary files /dev/null and b/client/src/assets/right-arrow.png differ diff --git a/client/src/contexts/application-context.tsx b/client/src/contexts/application-context.tsx new file mode 100644 index 00000000..3108aa17 --- /dev/null +++ b/client/src/contexts/application-context.tsx @@ -0,0 +1,16 @@ +import React, { createContext } from "react"; +import { Application } from "context.instance"; + +export const globalApplication = createContext(Application); + +export const ApplicationContextProvider = ({ + children +}: { + children: React.ReactNode; +}) => { + return ( + + {children} + + ); +}; diff --git a/client/src/contexts/messages-context.tsx b/client/src/contexts/messages-context.tsx index 21efb6d7..200ccaee 100644 --- a/client/src/contexts/messages-context.tsx +++ b/client/src/contexts/messages-context.tsx @@ -1,5 +1,6 @@ import React, { createContext, Dispatch, useReducer, useContext } from "react"; -import { Post, Profile } from "core/entity/post"; +import { Post } from "core/entity/post"; +import { Profile } from "core/entity/profile"; //코그 출처 https://velog.io/@velopert/typescript-context-api export type Action = diff --git a/client/src/contexts/path-parameter-context.tsx b/client/src/contexts/path-parameter-context.tsx index 045d84b1..6f86bf75 100644 --- a/client/src/contexts/path-parameter-context.tsx +++ b/client/src/contexts/path-parameter-context.tsx @@ -4,6 +4,10 @@ import { PathParameter } from "core/entity/path-parameter"; type Action = { type: "IN"; channelId: number; + +} | { + type: "GETSNUGID"; + snugId: number; }; type PathParameterDispatch = Dispatch; @@ -20,11 +24,14 @@ const PathParameterReducer = ( state: PathParameter, action: Action ): PathParameter => { + let newState: PathParameter = JSON.parse(JSON.stringify(state)); switch (action.type) { case "IN": - const newState: PathParameter = JSON.parse(JSON.stringify(state)); newState.channelId = action.channelId; return newState; + case "GETSNUGID": + newState.snugId = action.snugId; + return newState; } }; @@ -33,10 +40,7 @@ export const PathParameterContextProvider = ({ }: { children: React.ReactNode; }) => { - let path: PathParameter = { - channelId: -1 - }; - const [state, dispatch] = useReducer(PathParameterReducer, path); + const [state, dispatch] = useReducer(PathParameterReducer, {}); return ( diff --git a/client/src/contexts/socket-context.tsx b/client/src/contexts/socket-context.tsx new file mode 100644 index 00000000..b7d612ed --- /dev/null +++ b/client/src/contexts/socket-context.tsx @@ -0,0 +1,35 @@ +import React, { createContext, useContext } from "react"; +import socketIO from "socket.io-client"; + +const userSocket = socketIO( + process.env.REACT_APP_SOCKET_SERVER_HOST! + "/user", + { + transports: ["websocket"], + upgrade: false + } +); + +const snugSocket = socketIO( + process.env.REACT_APP_SOCKET_SERVER_HOST! + "/snug", + { + transports: ["websocket"], + upgrade: false + } +); + +const socket = { + userSocket, + snugSocket +}; + +export const globalSocket = createContext(socket); + +export const SocketContextProvider = ({ + children +}: { + children: React.ReactNode; +}) => { + return ( + {children} + ); +}; diff --git a/client/src/core/entity/invite.ts b/client/src/core/entity/invite.ts new file mode 100644 index 00000000..a876ac85 --- /dev/null +++ b/client/src/core/entity/invite.ts @@ -0,0 +1,7 @@ +export interface Invite { + id?: number; + email?: string; + snug?: string; + link?: string; + createAt?: Date; +} diff --git a/client/src/core/entity/path-parameter.ts b/client/src/core/entity/path-parameter.ts index 46209021..86a21222 100644 --- a/client/src/core/entity/path-parameter.ts +++ b/client/src/core/entity/path-parameter.ts @@ -1,3 +1,4 @@ export interface PathParameter { - channelId: number; + snugId?: number; + channelId?: number; } diff --git a/client/src/core/entity/post.tsx b/client/src/core/entity/post.tsx index 62f55456..42d6fb87 100644 --- a/client/src/core/entity/post.tsx +++ b/client/src/core/entity/post.tsx @@ -1,8 +1,4 @@ -export interface Profile { - id?: number; - thumbnail?: string; - name?: string; -} +import { Profile } from "./profile"; export interface Post { id?: number; @@ -10,4 +6,5 @@ export interface Post { updatedAt?: string; contents?: string; profile?: Profile; + room?: number; } diff --git a/client/src/core/entity/profile.ts b/client/src/core/entity/profile.ts new file mode 100644 index 00000000..492ad9af --- /dev/null +++ b/client/src/core/entity/profile.ts @@ -0,0 +1,16 @@ +export enum Role { + "admin" = "admin", + "member" = "member" +} + +export interface Profile { + id?: number; + thumbnail?: string; + name?: string; + status?: string; + role?: Role; + description?: string; + phone?: string; + email?: string; + snugId?: number; +} diff --git a/client/src/core/entity/snug.ts b/client/src/core/entity/snug.ts new file mode 100644 index 00000000..f78af396 --- /dev/null +++ b/client/src/core/entity/snug.ts @@ -0,0 +1,8 @@ +export interface Snug { + id?: number; + name?: string; + thumbnail?: string; + description?: string; + createdAt?: Date; + updatedAt?: Date; +} \ No newline at end of file diff --git a/client/src/core/entity/socket.ts b/client/src/core/entity/socket.ts new file mode 100644 index 00000000..d43fc923 --- /dev/null +++ b/client/src/core/entity/socket.ts @@ -0,0 +1,3 @@ +export interface Socket { + socket: SocketIOClient.Socket; +} diff --git a/client/src/core/entity/token.ts b/client/src/core/entity/token.ts new file mode 100644 index 00000000..e020b5f0 --- /dev/null +++ b/client/src/core/entity/token.ts @@ -0,0 +1,3 @@ +export interface WebToken { + token: T; +} diff --git a/client/src/core/entity/user.ts b/client/src/core/entity/user.ts new file mode 100644 index 00000000..03d4c916 --- /dev/null +++ b/client/src/core/entity/user.ts @@ -0,0 +1,6 @@ +export interface User { + id?: number; + email?: string; + name?: string; + password?: string; +} diff --git a/client/src/core/model/email-model.ts b/client/src/core/model/email-model.ts new file mode 100644 index 00000000..5e7be5c2 --- /dev/null +++ b/client/src/core/model/email-model.ts @@ -0,0 +1,33 @@ +export class EmailModel { + private static readonly DELIMITER = "@"; + private static readonly DEFAULT_EMAIL = ""; + private localPart: string; + private domain: string; + private readonly id: number; + + constructor(id: number, email?: string) { + this.id = id; + [this.localPart, this.domain] = this.tokenize(email || EmailModel.DEFAULT_EMAIL); + } + + private tokenize(email: string): string[] { + return email.split(EmailModel.DELIMITER); + } + + public changeEmail(email: string): EmailModel { + [this.localPart, this.domain] = this.tokenize(email); + return this; + } + + public getId() { + return this.id; + } + + public toString() { + return this.localPart + EmailModel.DELIMITER + this.domain; + } + + public hasEmail() { + return this.localPart && this.domain; + } +} \ No newline at end of file diff --git a/client/src/core/model/json-web-token-model.ts b/client/src/core/model/json-web-token-model.ts new file mode 100644 index 00000000..93c5a7b6 --- /dev/null +++ b/client/src/core/model/json-web-token-model.ts @@ -0,0 +1,7 @@ +import { WebToken } from "core/entity/token"; +export class JsonWebToken implements WebToken { + readonly token: string; + constructor(token: string) { + this.token = token; + } +} diff --git a/client/src/core/service/auth-service.ts b/client/src/core/service/auth-service.ts new file mode 100644 index 00000000..f3b32f8f --- /dev/null +++ b/client/src/core/service/auth-service.ts @@ -0,0 +1,32 @@ +import { User } from "core/entity/user"; +import { AuthRepositoryType } from "core/use-case/auth-repository-type"; + +export class AuthService { + private repository: AuthRepositoryType; + + constructor(repository: AuthRepositoryType) { + this.repository = repository; + } + + async login(email: string, password: string): Promise { + const user: User = { email, password }; + const JsonWebToken = await this.repository.login(user); + console.log(JsonWebToken); + if (!JsonWebToken.token) return false; + this.repository.setToken(JsonWebToken.token); + return true; + } + + getUserInfo(): User { + const user = this.repository.getUserInfo(); + return user; + } + + isLogined(): boolean { + return this.repository.isLogined(); + } + + logout(): boolean { + return this.repository.logout(); + } +} diff --git a/client/src/core/service/channel-service.ts b/client/src/core/service/channel-service.ts index 3859c052..0c460094 100644 --- a/client/src/core/service/channel-service.ts +++ b/client/src/core/service/channel-service.ts @@ -1,6 +1,7 @@ import { ChannelRepositoryType } from "core/use-case/channel-repository-type"; import { ChannelModel } from "core/model/channel-model"; import { Channel } from "core/entity/channel"; +import { Snug } from "core/entity/snug"; /** * @@ -25,14 +26,16 @@ export class ChannelService { * * */ async create( + snugId: number, title: string, description: string, privacy: boolean ): Promise { + const snug: Snug = { id: snugId }; const channel: ChannelModel = new ChannelModel(title, description, privacy); const satisfaction = await this.isSatisfied(channel); if (satisfaction) { - return this.repository.create(channel); + return this.repository.create(snug, channel); } return false; } @@ -61,7 +64,22 @@ export class ChannelService { return !redundancy; } - async getChannelList(): Promise { - return await this.repository.getChannels(); + async getChannelList(snugId: number): Promise { + const snug: Snug = { id: snugId }; + return await this.repository.getChannels(snug); + } + + async join(channelId: number): Promise { + const channel: Channel = { id: channelId }; + return await this.repository.join(channel); + } + // 이 서비스는 에러를 하단에서 보내기만 하고 처리해 주지 않으므로 ui내에서 error을 캐치하여 사용해야함 + async getParticipate(): Promise { + return await this.repository.getParticipateChannel(); + } + + async isInParticipating(channelId: number): Promise { + const channel: Channel = { id: channelId }; + return await this.repository.isInParticipating(channel); } } diff --git a/client/src/core/service/invite-service.ts b/client/src/core/service/invite-service.ts new file mode 100644 index 00000000..b6ae6632 --- /dev/null +++ b/client/src/core/service/invite-service.ts @@ -0,0 +1,43 @@ +import { InviteRepositoryType } from "core/use-case/invite-repository-type"; +import { EmailModel } from "core/model/email-model"; +import { Invite } from "core/entity/invite"; + +export class InviteService { + private repository: InviteRepositoryType; + + constructor(inviteRepository: InviteRepositoryType) { + this.repository = inviteRepository; + } + + private addEmailIfNotDuplicated(emails: string[], email: string): string[] { + if (!emails.includes(email)) { + return emails.concat(email); + } + + return emails; + } + + private transferToString(emails: EmailModel[]): string[] { + return emails + .filter(email => email.hasEmail()) + .map(email => email.toString()) + .reduce(this.addEmailIfNotDuplicated, []); + } + + async send(snugId: string, emailModels: EmailModel[]): Promise { + try { + const emails = this.transferToString(emailModels); + return await this.repository.send(snugId, emails); + } catch (error) { + return false; + } + } + + async getInvitedSnugs(userId: number): Promise { + return await this.repository.getInvitedSnugs(userId); + } + + async responseToInvitation(invitation: Invite, agree: boolean): Promise { + return await this.repository.responseToInvitation(invitation, agree); + } +} diff --git a/client/src/core/service/post-service.ts b/client/src/core/service/post-service.ts index 75b893a9..a7e7a930 100644 --- a/client/src/core/service/post-service.ts +++ b/client/src/core/service/post-service.ts @@ -1,5 +1,6 @@ import { Channel } from "core/entity/channel"; -import { Post, Profile } from "core/entity/post"; +import { Post } from "core/entity/post"; +import { Profile } from "core/entity/profile"; import { PostRepositoryType } from "core/use-case/post-repository-type"; export class PostService { diff --git a/client/src/core/service/profile-service.ts b/client/src/core/service/profile-service.ts new file mode 100644 index 00000000..819168ff --- /dev/null +++ b/client/src/core/service/profile-service.ts @@ -0,0 +1,39 @@ +import { Profile } from "core/entity/profile"; +import { ProfileRepositoryType } from "core/use-case/profile-repository-type"; + +export class ProfileService { + private static readonly PROFILE_NULL_OBJECT = {}; + private repository: ProfileRepositoryType; + + constructor(repository: ProfileRepositoryType) { + this.repository = repository; + } + + async getProfile(snugId: number): Promise { + try { + const profile = await this.repository.getProfile(); // 브라우저에서 프로필 존재 유무 확인 + if (this.hasVisitedPreviousSnug(snugId, profile)) { + return profile; + } + } finally { + return await this.retryFetchProfileToken(snugId); + } + } + + private hasVisitedPreviousSnug(snugId: number, profile: Profile): boolean { + return profile && profile.snugId === snugId; + } + + private async retryFetchProfileToken(snugId: number): Promise { + try { + await this.repository.getProfileToken(snugId); // 서버에서 만든 새로운 토큰을 조회 + return await this.repository.getProfile(); + } catch (error) { + return {}; + } + } + + async updateProfile(profile: Profile): Promise { + return await this.repository.updateProfile(profile); + } +} diff --git a/client/src/core/service/snug-service.ts b/client/src/core/service/snug-service.ts new file mode 100644 index 00000000..4943276a --- /dev/null +++ b/client/src/core/service/snug-service.ts @@ -0,0 +1,23 @@ +import { Snug } from "core/entity/snug"; +import { SnugRepositoryType } from "core/use-case/snug-repository-type"; + +export class SnugService { + private repository: SnugRepositoryType; + + constructor(repository: SnugRepositoryType) { + this.repository = repository; + } + + async createSnug( + name: string, + description: string, + thumbnail: string + ): Promise { + const snug: Snug = { name, description, thumbnail }; + return await this.repository.create(snug); + } + + async getList(): Promise { + return await this.repository.getList(); + } +} diff --git a/client/src/core/service/user-service.ts b/client/src/core/service/user-service.ts new file mode 100644 index 00000000..24b5cc74 --- /dev/null +++ b/client/src/core/service/user-service.ts @@ -0,0 +1,25 @@ +import { User } from "core/entity/user"; +import { UserRepositoryType } from "core/use-case/user-repository-type"; + +export class UserService { + private repository: UserRepositoryType; + + constructor(repository: UserRepositoryType) { + this.repository = repository; + } + + /** + * + * User 생성하기 위한 함수 + * @param user + * + * */ + async create(user: User): Promise { + return await this.repository.create(user); + } + + async doesExist(email: string): Promise { + const existence = await this.repository.doesEmailExist(email); + return existence; + } +} diff --git a/client/src/core/use-case/auth-repository-type.ts b/client/src/core/use-case/auth-repository-type.ts new file mode 100644 index 00000000..6766ea5c --- /dev/null +++ b/client/src/core/use-case/auth-repository-type.ts @@ -0,0 +1,14 @@ +import { User } from "core/entity/user"; +import { WebToken } from "core/entity/token"; + +export interface AuthRepositoryType { + setToken(token: string): void; + + getUserInfo(): User; + + login(user: User): Promise>; + + isLogined(): boolean; + + logout(): boolean; +} diff --git a/client/src/core/use-case/channel-repository-type.ts b/client/src/core/use-case/channel-repository-type.ts index 76ec72df..6cd50dea 100644 --- a/client/src/core/use-case/channel-repository-type.ts +++ b/client/src/core/use-case/channel-repository-type.ts @@ -1,9 +1,16 @@ import { Channel } from "core/entity/channel"; +import { Snug } from "core/entity/snug"; export interface ChannelRepositoryType { - create(channel: Channel): Promise; + create(snug: Snug, channel: Channel): Promise; hasByTitle(title: string): Promise; - getChannels(): Promise; + join(channel: Channel): Promise; + + getChannels(snug: Snug): Promise; + + getParticipateChannel(): Promise; + + isInParticipating(channel: Channel): Promise; } diff --git a/client/src/core/use-case/invite-repository-type.ts b/client/src/core/use-case/invite-repository-type.ts new file mode 100644 index 00000000..ba27beb7 --- /dev/null +++ b/client/src/core/use-case/invite-repository-type.ts @@ -0,0 +1,9 @@ +import { Invite } from "core/entity/invite"; + +export interface InviteRepositoryType { + send(snugId: string, emails: string[]): Promise; + + getInvitedSnugs(userId: number): Promise; + + responseToInvitation(invitation: Invite, agree: boolean): Promise; +} diff --git a/client/src/core/use-case/post-repository-type.ts b/client/src/core/use-case/post-repository-type.ts index f3dafc73..1d776851 100644 --- a/client/src/core/use-case/post-repository-type.ts +++ b/client/src/core/use-case/post-repository-type.ts @@ -1,5 +1,6 @@ import { Channel } from "core/entity/channel"; -import { Post, Profile } from "core/entity/post"; +import { Post } from "core/entity/post"; +import { Profile } from "core/entity/profile"; export interface PostRepositoryType { getList(channel: Channel): Promise; diff --git a/client/src/core/use-case/profile-repository-type.ts b/client/src/core/use-case/profile-repository-type.ts new file mode 100644 index 00000000..e4939027 --- /dev/null +++ b/client/src/core/use-case/profile-repository-type.ts @@ -0,0 +1,7 @@ +import { Profile } from "core/entity/profile"; + +export interface ProfileRepositoryType { + getProfile(): Promise; + updateProfile(profile: Profile): Promise; + getProfileToken(snugId: number): Promise; +} diff --git a/client/src/core/use-case/snug-repository-type.ts b/client/src/core/use-case/snug-repository-type.ts new file mode 100644 index 00000000..bf189c28 --- /dev/null +++ b/client/src/core/use-case/snug-repository-type.ts @@ -0,0 +1,11 @@ +import { Snug } from "core/entity/snug"; + +export interface SnugRepositoryType { + /** + * snug를 생성한다. + * @param userId snug creator + */ + create(snug: Snug): Promise; + + getList(): Promise; +} diff --git a/client/src/core/use-case/user-repository-type.ts b/client/src/core/use-case/user-repository-type.ts new file mode 100644 index 00000000..2d92b35f --- /dev/null +++ b/client/src/core/use-case/user-repository-type.ts @@ -0,0 +1,7 @@ +import { User } from "core/entity/user"; + +export interface UserRepositoryType { + create(user: User): Promise; + + doesEmailExist(email: string): Promise; +} diff --git a/client/src/core/utility/array-helper.ts b/client/src/core/utility/array-helper.ts new file mode 100644 index 00000000..99c941fb --- /dev/null +++ b/client/src/core/utility/array-helper.ts @@ -0,0 +1,17 @@ +export class ArrayHelper { + static generateUntil(limit: number) { + const array = []; + for (let num = 0; num < limit; ++num) { + array.push(num); + } + return array; + }; + + static has(array: T[]) { + return array && array.length > 0; + }; + + static hasNot(array: T[]) { + return !ArrayHelper.has(array); + }; +} \ No newline at end of file diff --git a/client/src/core/utility/compose-helper.ts b/client/src/core/utility/compose-helper.ts new file mode 100644 index 00000000..bae5e4e4 --- /dev/null +++ b/client/src/core/utility/compose-helper.ts @@ -0,0 +1,7 @@ +// 그룹 프로젝트 수업 자료 참고 +export const pipe = (...functions: any) => (...args: any) => functions.reduce((arg: any, nextFunction: any) => { + if (Array.isArray(arg)) { + return nextFunction(...arg); + } + return nextFunction(arg); +}, args); \ No newline at end of file diff --git a/client/src/data/browser-storage/browser-storage-helper.ts b/client/src/data/browser-storage/browser-storage-helper.ts new file mode 100644 index 00000000..951191c8 --- /dev/null +++ b/client/src/data/browser-storage/browser-storage-helper.ts @@ -0,0 +1,39 @@ +export enum StorageType { + LOCAL = "local", + SESSION = "session" +} + +export type BrowserStorageKey = string; + +export class BrowserStorageHelper { + private storageType: StorageType; + private storage: Storage; + + constructor(storageType: StorageType) { + this.storageType = storageType; + this.storage = this.setStorage(this.storageType); + } + + private setStorage(storageType: StorageType) { + switch (storageType) { + case StorageType.LOCAL: + return localStorage; + case StorageType.SESSION: + return sessionStorage; + default: + throw new Error("존재하지 않는 스토리지 입니다."); + } + } + + get(key: BrowserStorageKey) { + return this.storage.getItem(key); + } + + set(key: BrowserStorageKey, target: string) { + this.storage.setItem(key, target); + } + + clear(key: BrowserStorageKey) { + this.storage.removeItem(key); + } +} diff --git a/client/src/data/browser-storage/browser-storage-mapper.ts b/client/src/data/browser-storage/browser-storage-mapper.ts new file mode 100644 index 00000000..dee62e1e --- /dev/null +++ b/client/src/data/browser-storage/browser-storage-mapper.ts @@ -0,0 +1,6 @@ +export interface BrowserStorageMapper { + fromJson(json: string): E; + toJson(target: E): string; +} + +//참고 : https://medium.com/rainist-engineering/safe-localstorage-using-typescdript-eac147f59ae diff --git a/client/src/data/browser-storage/browser-storage.ts b/client/src/data/browser-storage/browser-storage.ts new file mode 100644 index 00000000..7d120cdc --- /dev/null +++ b/client/src/data/browser-storage/browser-storage.ts @@ -0,0 +1,44 @@ +import { BrowserStorageMapper } from "./browser-storage-mapper"; +import { + BrowserStorageKey, + BrowserStorageHelper, + StorageType +} from "./browser-storage-helper"; + +export class BrowserStorage { + private key: BrowserStorageKey; + private mapper: BrowserStorageMapper; + private helper: BrowserStorageHelper; + + constructor( + key: BrowserStorageKey, + mapper: BrowserStorageMapper, + storageType: StorageType + ) { + this.key = key; + this.mapper = mapper; + this.helper = new BrowserStorageHelper(storageType); + } + + isNull(value: any) { + if (value == null) return true; + return false; + } + + get(): E | null { + const value = this.helper.get(this.key); + if (this.isNull(value)) return null; + return this.mapper.fromJson(value!); + } + + set(target: E) { + const targetValue = this.mapper.toJson(target); + this.helper.set(this.key, targetValue); + } + + clear() { + this.helper.clear(this.key); + } +} + +//참고 : https://medium.com/rainist-engineering/safe-localstorage-using-typescdript-eac147f59ae diff --git a/client/src/data/browser-storage/custom-mapper/json-web-tocken-mapper.ts b/client/src/data/browser-storage/custom-mapper/json-web-tocken-mapper.ts new file mode 100644 index 00000000..730725f3 --- /dev/null +++ b/client/src/data/browser-storage/custom-mapper/json-web-tocken-mapper.ts @@ -0,0 +1,13 @@ +import { BrowserStorageMapper } from "../browser-storage-mapper"; +import { JsonWebToken } from "core/model/json-web-token-model"; +export class JsonWebTokenMapper implements BrowserStorageMapper { + fromJson(json: string) { + const value = JSON.parse(json); + return new JsonWebToken(value.token); + } + toJson(target: JsonWebToken) { + return JSON.stringify({ + token: target.token + }); + } +} diff --git a/client/src/data/http/api/auth-api.ts b/client/src/data/http/api/auth-api.ts new file mode 100644 index 00000000..d4bd9bc2 --- /dev/null +++ b/client/src/data/http/api/auth-api.ts @@ -0,0 +1,34 @@ +import { User } from "core/entity/user"; +import { AxiosErrorHandler } from "data/http/api/axiosErrorHandler"; +import { StatusCodes } from "./status-codes"; +import { AxiosResponse, AxiosError, AxiosInstance } from "axios"; +import { AxiosWrapper } from "./axios-wrapper"; +import { ResponseEntity } from "./response/ResponseEntity"; +import { WebToken } from "core/entity/token"; + +export class AuthApi { + private axios: AxiosInstance; + + constructor(axios: AxiosWrapper) { + this.axios = axios.getAxios(); + } + + login(user: User): Promise> | boolean> { + return this.axios + .post("/api/auth/login", user) + .then( + ({ data, status }: AxiosResponse>>) => { + if (StatusCodes.isOk(status)) { + return data; + } + throw new Error("로그인에 실패 했습니다."); + } + ) + .catch((error: AxiosError) => { + return AxiosErrorHandler.handleError( + error, + `로그인을 하는 과정에서 문제가 발생했습니다. : ${error.message}` + ); + }); + } +} diff --git a/client/src/data/http/api/axios-wrapper.ts b/client/src/data/http/api/axios-wrapper.ts index 1e1f9bde..63c89c49 100644 --- a/client/src/data/http/api/axios-wrapper.ts +++ b/client/src/data/http/api/axios-wrapper.ts @@ -1,20 +1,38 @@ -import axios from 'axios'; +import axios, { AxiosRequestConfig, AxiosStatic } from "axios"; +import { BrowserStorage } from "data/browser-storage/browser-storage"; +import { JsonWebToken } from "core/model/json-web-token-model"; +import { JsonWebTokenMapper } from "data/browser-storage/custom-mapper/json-web-tocken-mapper"; +import { StorageType } from "data/browser-storage/browser-storage-helper"; + +const jwtLocal = new BrowserStorage( + "jwt", + new JsonWebTokenMapper(), + StorageType.LOCAL +); export class AxiosWrapper { + private axios: AxiosStatic; constructor() { + this.axios = axios; this.initialize(); } private initialize(): void { - if(process.env.NODE_ENV !== "development") { - axios.defaults.baseURL = process.env.REACT_APP_API_SERVER_HOST; + if (process.env.NODE_ENV !== "development") { + this.axios.defaults.baseURL = process.env.REACT_APP_API_SERVER_HOST; } - axios.defaults.headers.common['Content-Type'] = 'application/json'; - axios.defaults.headers.common['Accept'] = 'application/json'; + this.axios.defaults.headers.common["Content-Type"] = "application/json"; + this.axios.defaults.headers.common["Accept"] = "application/json"; } public getAxios() { - return axios.create(); + if (jwtLocal.get() == null) return this.axios.create(); + else + return this.axios.create({ + headers: { + "Auth-Token": jwtLocal.get()!.token + } + }); } -} \ No newline at end of file +} diff --git a/client/src/data/http/api/channel-api.ts b/client/src/data/http/api/channel-api.ts index be216043..f07343e5 100644 --- a/client/src/data/http/api/channel-api.ts +++ b/client/src/data/http/api/channel-api.ts @@ -1,20 +1,26 @@ import { AxiosErrorHandler } from "data/http/api/axiosErrorHandler"; import { Channel } from "core/entity/channel"; -import { AxiosError, AxiosResponse } from "axios"; +import { AxiosError, AxiosResponse, AxiosInstance } from "axios"; import { ResponseEntity } from "./response/ResponseEntity"; import { StatusCodes } from "./status-codes"; import { AxiosWrapper } from "./axios-wrapper"; +import { Snug } from "core/entity/snug"; export class ChannelApi { - private axios: any; + private axios: AxiosWrapper; constructor(axios: AxiosWrapper) { - this.axios = axios.getAxios(); + this.axios = axios; } - create(channel: Channel): ResponseEntity | boolean { + create( + snug: Snug, + channel: Channel + ): Promise | boolean> { return this.axios + .getAxios() .post(`/api/channels`, { + snugId: snug.id!, title: channel.title!, description: channel.description!, privacy: channel.privacy! @@ -34,8 +40,9 @@ export class ChannelApi { ); } - findByTitle(title: string): ResponseEntity | boolean { + findByTitle(title: string): Promise | boolean> { return this.axios + .getAxios() .get(`/api/channels/${title}`) .then((response: AxiosResponse>) => { if (StatusCodes.isOk(response.status)) { @@ -52,18 +59,46 @@ export class ChannelApi { ); } - getList(): ResponseEntity | boolean { + getList(snug: Snug): Promise | boolean> { return this.axios - .get("/api/channels") + .getAxios() + .get(`/api/snugs/${snug.id!}/channels`) .then((response: AxiosResponse>) => { if (StatusCodes.isOk(response.status)) return response.data; return false; }) .catch((error: AxiosError) => { - AxiosErrorHandler.handleError( + return AxiosErrorHandler.handleError( error, `채널 목록을 불러오는 과정에서 예기치 못한 에러가 발생했습니다.` ); }); } + + join(channel: Channel): Promise { + return this.axios + .getAxios() + .post(`/api/channels/join`, { + channelId: channel.id + }) + .then((response: AxiosResponse>) => { + return StatusCodes.isOk(response.status); + }) + .catch(() => { + return false; + }); + } + + getParticipate(): Promise> { + return this.axios + .getAxios() + .get("/api/participateins") + .then(({ status, data }: AxiosResponse>) => { + if (StatusCodes.isOk(status)) return data; + throw new Error("참여한 채널을 가지고 오는 과정에서 문제가 있습니다."); + }) + .catch(err => { + throw new Error(err.message); + }); + } } diff --git a/client/src/data/http/api/invite-api.ts b/client/src/data/http/api/invite-api.ts new file mode 100644 index 00000000..b2f7a38d --- /dev/null +++ b/client/src/data/http/api/invite-api.ts @@ -0,0 +1,67 @@ +import { AxiosWrapper } from "./axios-wrapper"; +import { AxiosError, AxiosResponse } from "axios"; +import { ResponseEntity } from "data/http/api/response/ResponseEntity"; +import { StatusCodes } from "data/http/api/status-codes"; +import { AxiosErrorHandler } from "data/http/api/axiosErrorHandler"; +import { Invite } from "core/entity/invite"; + +export class InviteApi { + private axios: any; + + constructor(axios: AxiosWrapper) { + this.axios = axios.getAxios(); + } + + sendEmails(snugId: string, emails: string[]) { + return this.axios + .post(`/api/snugs/${snugId}/invite`, { snugId, emails }) + .then((response: AxiosResponse>) => + StatusCodes.isOk(response.status) + ) + .catch((error: AxiosError) => + AxiosErrorHandler.handleError( + error, + `${emails!} 추가 과정에서 예기치 못한 에러가 발생했습니다.` + ) + ); + } + + getInvitedSnugs(userId: number): Promise | boolean> { + return this.axios + .get(`/api/users/${userId}/invite`) + .then((response: AxiosResponse>) => { + if (StatusCodes.isOk(response.status)) { + return response.data; + } else { + return false; + } + }) + .catch((error: AxiosError) => + AxiosErrorHandler.handleError( + error, + `${userId} 기반으로 snug 조회 과정에서 예기치 못한 에러가 발생했습니다.` + ) + ); + } + + responseToInvitation( + invite: Invite, agree: boolean + ): Promise | boolean> { + return this.axios + .post(invite.link, { agree }) + .then((response: AxiosResponse>) => { + console.log(response); + if (StatusCodes.isAccepted(response.status)) { + return response.data; + } else { + return false; + } + }) + .catch((error: AxiosError) => + AxiosErrorHandler.handleError( + error, + `${invite.snug} 추가 과정에서 예기치 못한 에러가 발생했습니다.` + ) + ); + } +} diff --git a/client/src/data/http/api/post-api.ts b/client/src/data/http/api/post-api.ts index c3cf82b9..f8d17321 100644 --- a/client/src/data/http/api/post-api.ts +++ b/client/src/data/http/api/post-api.ts @@ -1,5 +1,6 @@ import { AxiosErrorHandler } from "data/http/api/axiosErrorHandler"; -import { Post, Profile } from "core/entity/post"; +import { Post } from "core/entity/post"; +import { Profile } from "core/entity/profile"; import { Channel } from "core/entity/channel"; import { StatusCodes } from "./status-codes"; import { AxiosResponse, AxiosError } from "axios"; diff --git a/client/src/data/http/api/profile-api.ts b/client/src/data/http/api/profile-api.ts new file mode 100644 index 00000000..34d9f6e2 --- /dev/null +++ b/client/src/data/http/api/profile-api.ts @@ -0,0 +1,44 @@ +import { AxiosErrorHandler } from "data/http/api/axiosErrorHandler"; +import { Profile } from "core/entity/profile"; +import { StatusCodes } from "./status-codes"; +import { AxiosInstance, AxiosResponse, AxiosError } from "axios"; +import { AxiosWrapper } from "./axios-wrapper"; +import { ResponseEntity } from "./response/ResponseEntity"; + +export class ProfileApi { + private axios: AxiosInstance; + constructor(axios: AxiosWrapper) { + this.axios = axios.getAxios(); + } + + updateProfile(profile: Profile): Promise | boolean> { + return this.axios + .patch(`/api/profiles/${profile.id}`, profile) + .then((response: AxiosResponse>) => { + if (StatusCodes.isAccepted(response.status)) return response.data; + return false; + }) + .catch((error: AxiosError) => { + return AxiosErrorHandler.handleError( + error, + `프로필을 갱신하는 과정에서 오류가 발생했습니다 : ${error.message}` + ); + }); + } + + getProfileToken(snugId: number): Promise { + return this.axios + .get(`/api/auth/snugs/${snugId}/profiles`) + .then(({ status }: AxiosResponse>) => { + if (StatusCodes.isNotOk(status)) { + throw new Error("프로필 토큰 조회에 실패 했습니다."); + } + }) + .catch((error: AxiosError) => { + AxiosErrorHandler.handleError( + error, + `프로필 토큰을 조회하는 과정에서 문제가 발생했습니다. : ${error.message}` + ); + }); + } +} diff --git a/client/src/data/http/api/snug-api.ts b/client/src/data/http/api/snug-api.ts new file mode 100644 index 00000000..63e1a3f5 --- /dev/null +++ b/client/src/data/http/api/snug-api.ts @@ -0,0 +1,53 @@ +import { AxiosErrorHandler } from "data/http/api/axiosErrorHandler"; +import { Snug } from "core/entity/snug"; +import { StatusCodes } from "./status-codes"; +import { AxiosInstance, AxiosResponse, AxiosError } from "axios"; +import { AxiosWrapper } from "./axios-wrapper"; +import { ResponseEntity } from "./response/ResponseEntity"; + +export class SnugApi { + private axios: AxiosInstance; + constructor(axios: AxiosWrapper) { + this.axios = axios.getAxios(); + } + + create(input: Snug): Promise | boolean> { + return this.axios + .post(`/api/snugs`, { + name: input.name, + description: input.description, + thumbnail: input.thumbnail + }) + .then((response: AxiosResponse>) => { + if (StatusCodes.isCreated(response.status)) { + return response.data; + } else { + return false; + } + }) + .catch((error: AxiosError) => + AxiosErrorHandler.handleError( + error, + `${input.name!} 추가 과정에서 예기치 못한 에러가 발생했습니다.` + ) + ); + } + + getList(): Promise | boolean> { + return this.axios + .get(`/api/snugs`) + .then((response: AxiosResponse>) => { + if (StatusCodes.isOk(response.status)) { + return response.data; + } else { + return false; + } + }) + .catch((error: AxiosError) => + AxiosErrorHandler.handleError( + error, + `채널을 불러오는 과정에서 예기치 못한 에러가 발생했습니다.` + ) + ); + } +} diff --git a/client/src/data/http/api/status-codes.ts b/client/src/data/http/api/status-codes.ts index 452b2ebe..30fa8b68 100644 --- a/client/src/data/http/api/status-codes.ts +++ b/client/src/data/http/api/status-codes.ts @@ -1,6 +1,7 @@ enum StatusCode { CREATED = 201, - OK = 200 + OK = 200, + ACCEPTED = 202 } export class StatusCodes { @@ -8,7 +9,15 @@ export class StatusCodes { return StatusCode.OK === code; } + public static isNotOk(code: number): boolean { + return !StatusCodes.isOk(code); + } + public static isCreated(code: number): boolean { return StatusCode.CREATED === code; } -} \ No newline at end of file + + public static isAccepted(code: number): boolean { + return StatusCode.ACCEPTED === code; + } +} diff --git a/client/src/data/http/api/user-api.ts b/client/src/data/http/api/user-api.ts new file mode 100644 index 00000000..2ab4a63c --- /dev/null +++ b/client/src/data/http/api/user-api.ts @@ -0,0 +1,54 @@ +import { AxiosErrorHandler } from "data/http/api/axiosErrorHandler"; +import { User } from "core/entity/user"; +import { AxiosError, AxiosResponse } from "axios"; +import { ResponseEntity } from "./response/ResponseEntity"; +import { StatusCodes } from "./status-codes"; +import { AxiosWrapper } from "./axios-wrapper"; + +export class UserApi { + private axios: any; + + constructor(axios: AxiosWrapper) { + this.axios = axios.getAxios(); + } + + create(user: User): ResponseEntity | boolean { + return this.axios + .post(`api/users`, { + email: user.email, + name: user.name, + password: user.password + }) + .then((response: AxiosResponse>) => { + if (StatusCodes.isCreated(response.status)) { + return response.data; + } else { + return false; + } + }) + .catch((error: AxiosError) => + AxiosErrorHandler.handleError( + error, + `${user.email!} 추가 과정에서 예기치 못한 에러가 발생했습니다.` + ) + ); + } + + findByEmail(email: string): ResponseEntity | boolean { + return this.axios + .get(`/api/users/email/${email}`) + .then((response: AxiosResponse>) => { + if (StatusCodes.isOk(response.status)) { + return response.data; + } else { + return false; + } + }) + .catch((error: AxiosError) => + AxiosErrorHandler.handleError( + error, + `${email} 조회 과정에서 예기치 못한 에러가 발생했습니다.` + ) + ); + } +} diff --git a/client/src/data/repository/auth-repository.ts b/client/src/data/repository/auth-repository.ts new file mode 100644 index 00000000..ffceffa2 --- /dev/null +++ b/client/src/data/repository/auth-repository.ts @@ -0,0 +1,70 @@ +import { JsonWebToken } from "core/model/json-web-token-model"; +import { AuthRepositoryType } from "core/use-case/auth-repository-type"; +import { AuthApi } from "data/http/api/auth-api"; +import { BrowserStorage } from "data/browser-storage/browser-storage"; +import jwt from "jsonwebtoken"; +import { User } from "core/entity/user"; +import { WebToken } from "core/entity/token"; + +export class AuthRepository implements AuthRepositoryType { + private api: AuthApi; + private storage: BrowserStorage; + + constructor(api: AuthApi, storage: BrowserStorage) { + this.api = api; + this.storage = storage; + } + + getUserInfo(): User { + try { + const result = this.storage.get(); + if (result == null) return {}; + const payload: { [key: string]: any } = jwt.decode(result.token); + const user: User = { + email: payload.email, + id: payload.id + }; + return user; + } catch (error) { + return {}; + } + } + + setToken(token: string): void { + try { + this.storage.set(new JsonWebToken(token)); + } catch (error) { + return; + } + } + + async login(user: User): Promise> { + try { + const result = await this.api.login(user); + if (typeof result === "boolean") + throw new Error("로그인에 실패했습니다."); + return result.payload; + } catch (error) { + return { token: "" }; + } + } + + isLogined(): boolean { + try { + const result = this.storage.get(); + if (result == null) return false; + return true; + } catch (error) { + return false; + } + } + + logout(): boolean { + try { + this.storage.clear(); + return true; + } catch (error) { + return false; + } + } +} diff --git a/client/src/data/repository/channel-repository.ts b/client/src/data/repository/channel-repository.ts index bfe65e9a..09fc8f2d 100644 --- a/client/src/data/repository/channel-repository.ts +++ b/client/src/data/repository/channel-repository.ts @@ -2,6 +2,7 @@ import { ResponseEntity } from "./../http/api/response/ResponseEntity"; import { ChannelApi } from "../http/api/channel-api"; import { Channel } from "../../core/entity/channel"; import { ChannelRepositoryType } from "../../core/use-case/channel-repository-type"; +import { Snug } from "core/entity/snug"; export class ChannelRepository implements ChannelRepositoryType { private api: ChannelApi; @@ -10,9 +11,9 @@ export class ChannelRepository implements ChannelRepositoryType { this.api = api; } - async create(channel: Channel): Promise { + async create(snug: Snug, channel: Channel): Promise { try { - const responseEntity = await this.api.create(channel); + const responseEntity = await this.api.create(snug, channel); if (typeof responseEntity == "boolean") return false; return (>responseEntity).payload; } catch (error) { @@ -29,14 +30,36 @@ export class ChannelRepository implements ChannelRepositoryType { } } - async getChannels(): Promise { + async getChannels(snug: Snug): Promise { try { - const ResponseEntity = await this.api.getList(); - if (ResponseEntity) - return (>ResponseEntity).payload; + const responseEntity = await this.api.getList(snug); + if (responseEntity) + return (>responseEntity).payload; return false; } catch (error) { return false; } } + + async join(channel: Channel): Promise { + return await this.api.join(channel); + } + + async getParticipateChannel(): Promise { + if (document.cookie.indexOf("profile") == -1) + throw new Error("프로필 쿠키가 존재하지 않습니다."); + const responseEntity = await this.api.getParticipate(); + return responseEntity.payload; + } + + async isInParticipating(channel: Channel): Promise { + if (document.cookie.indexOf("profile") == -1) + throw new Error("프로필 쿠키가 존재하지 않습니다."); + const { payload } = await this.api.getParticipate(); + const result = payload.filter( + channelParameter => channelParameter.id == channel.id + ); + if (result.length <= 0) return false; + return true; + } } diff --git a/client/src/data/repository/invite-repository.ts b/client/src/data/repository/invite-repository.ts new file mode 100644 index 00000000..68f91a51 --- /dev/null +++ b/client/src/data/repository/invite-repository.ts @@ -0,0 +1,36 @@ +import { ResponseEntity } from "./../http/api/response/ResponseEntity"; +import { InviteRepositoryType } from "core/use-case/invite-repository-type"; +import { InviteApi } from "data/http/api/invite-api"; +import { Invite } from "core/entity/invite"; + +export class InviteRepository implements InviteRepositoryType { + private readonly inviteApi: InviteApi; + + constructor(inviteApi: InviteApi) { + this.inviteApi = inviteApi; + } + + async send(snugId: string, emails: string[]): Promise { + return await this.inviteApi.sendEmails(snugId, emails); + } + + async getInvitedSnugs(userId: number): Promise { + try { + const responseEntity = await this.inviteApi.getInvitedSnugs(userId); + if (!responseEntity) return false; + return (>responseEntity).payload; + } catch (error) { + return false; + } + } + + async responseToInvitation(invitation: Invite, agree: boolean): Promise { + try { + const responseEntity = await this.inviteApi.responseToInvitation(invitation, agree); + if (!responseEntity) return false; + return (>responseEntity).payload; + } catch (error) { + return false; + } + } +} diff --git a/client/src/data/repository/post-repository.ts b/client/src/data/repository/post-repository.ts index ef8d5230..daea0ba5 100644 --- a/client/src/data/repository/post-repository.ts +++ b/client/src/data/repository/post-repository.ts @@ -1,6 +1,6 @@ import { ResponseEntity } from "data/http/api/response/ResponseEntity"; import { Post } from "core/entity/post"; -import { Profile } from "core/entity/post"; +import { Profile } from "core/entity/profile"; import { Channel } from "core/entity/channel"; import { PostRepositoryType } from "core/use-case/post-repository-type"; import { PostApi, posts } from "data/http/api/post-api"; diff --git a/client/src/data/repository/profile-repository.ts b/client/src/data/repository/profile-repository.ts new file mode 100644 index 00000000..eff851f5 --- /dev/null +++ b/client/src/data/repository/profile-repository.ts @@ -0,0 +1,42 @@ +import { ResponseEntity } from "data/http/api/response/ResponseEntity"; +import { ProfileRepositoryType } from "core/use-case/profile-repository-type"; +import { ProfileApi } from "data/http/api/profile-api"; +import { Profile } from "core/entity/profile"; +import { getCookie } from "util/cookie"; +import jwt from "jsonwebtoken"; + +export class ProfileRepository implements ProfileRepositoryType { + private api: ProfileApi; + + constructor(api: ProfileApi) { + this.api = api; + } + + async getProfile(): Promise { + try { + const token: string | boolean = getCookie("profile"); + if (typeof token === "boolean") + throw new Error("프로필 쿠키가 존재하지 않습니다."); + const profile: Profile = jwt.decode(token); + return profile; + } catch (error) { + throw new Error(error.message); + } + } + + async updateProfile(profile: Profile): Promise { + try { + const responseEntity = await this.api.updateProfile(profile); + if ((>responseEntity).payload) { + return (>responseEntity).payload; + } + return responseEntity; + } catch (error) { + return false; + } + } + + async getProfileToken(snugId: number): Promise { + return await this.api.getProfileToken(snugId); + } +} diff --git a/client/src/data/repository/snug-repository.ts b/client/src/data/repository/snug-repository.ts new file mode 100644 index 00000000..48ebcb05 --- /dev/null +++ b/client/src/data/repository/snug-repository.ts @@ -0,0 +1,31 @@ +import { ResponseEntity } from "./../http/api/response/ResponseEntity"; +import { SnugApi } from "data/http/api/snug-api"; +import { Snug } from "../../core/entity/snug"; +import { SnugRepositoryType } from "../../core/use-case/snug-repository-type"; + +export class SnugRepository implements SnugRepositoryType { + private api: SnugApi; + + constructor(api: SnugApi) { + this.api = api; + } + + async create(snug: Snug): Promise { + try { + const responseEntity = await this.api.create(snug); + if (typeof responseEntity === "boolean") return false; + return (>responseEntity).payload; + } catch (error) { + return false; + } + } + + async getList(): Promise { + try { + const responseEntity = await this.api.getList(); + return (>responseEntity).payload; + } catch (error) { + return false; + } + } +} diff --git a/client/src/data/repository/user-repository.ts b/client/src/data/repository/user-repository.ts new file mode 100644 index 00000000..da813a64 --- /dev/null +++ b/client/src/data/repository/user-repository.ts @@ -0,0 +1,31 @@ +import { ResponseEntity } from "data/http/api/response/ResponseEntity"; +import { UserApi } from "data/http/api/user-api"; +import { User } from "core/entity/user"; +import { UserRepositoryType } from "core/use-case/user-repository-type"; + +export class UserRepository implements UserRepositoryType { + private api: UserApi; + + constructor(api: UserApi) { + this.api = api; + } + + async create(user: User): Promise { + try { + const responseEntity = await this.api.create(user); + console.log(responseEntity); + return !!responseEntity; + } catch (error) { + return false; + } + } + + async doesEmailExist(email: string): Promise { + try { + const responseEntity = await this.api.findByEmail(email); + return !!responseEntity; + } catch (error) { + return false; + } + } +} diff --git a/client/src/presentation/components/atomic-reusable/custom-button.tsx b/client/src/presentation/components/atomic-reusable/custom-button.tsx index 434e22f4..dbcdab5c 100644 --- a/client/src/presentation/components/atomic-reusable/custom-button.tsx +++ b/client/src/presentation/components/atomic-reusable/custom-button.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useEffect } from "react"; import styled, { css } from "styled-components"; export type ButtonType = "button" | "submit" | "reset" | undefined; @@ -13,6 +13,8 @@ export interface CustomButtonConfig { type?: ButtonType; borderColor?: string; height?: string; + disabled?: boolean; + disabledColor?: string; onClick?(parameter: any | void): any | void; } @@ -36,9 +38,9 @@ const Button = styled.button` &:hover { opacity: 0.5; } + cursor: pointer; ${(props: CustomButtonConfig) => { const size = props.size ? determineSize(props.size) : ""; - const color = props.color ? props.color : "#ffffff"; const fontColor = props.fontColor ? props.fontColor : "#000000"; const fontWeight = props.fontWeight ? props.fontWeight : "0"; const fontSize = props.fontSize ? props.fontSize : "1rem"; @@ -46,6 +48,9 @@ const Button = styled.button` ? `1px solid ${props.borderColor}` : "none"; const height = props.height ? props.height : "30px"; + const disableHover = props.disabled ? "none" : ""; + let color = props.color ? props.color : "#ffffff"; + color = props.disabled && props.disabledColor ? props.disabledColor : color; return css` background-color: ${color}; @@ -55,7 +60,8 @@ const Button = styled.button` font-weight: ${fontWeight}; font-size: ${fontSize}; border: ${border}; - heigth: ${height}; + height: ${height}; + pointer-events: ${disableHover}; `; }}; `; @@ -70,7 +76,9 @@ export const CustomButton: React.FC = ({ fontSize, onClick, borderColor, - height + height, + disabled = false, + disabledColor }) => { return ( diff --git a/client/src/presentation/components/atomic-reusable/custom-login-input.tsx b/client/src/presentation/components/atomic-reusable/custom-login-input.tsx index 4e9ffd78..b6f0822e 100644 --- a/client/src/presentation/components/atomic-reusable/custom-login-input.tsx +++ b/client/src/presentation/components/atomic-reusable/custom-login-input.tsx @@ -2,11 +2,14 @@ import React from "react"; import styled, { css } from "styled-components"; export interface CustomLoginInput { + value?: string; color?: string; fontSize?: string; activeHoverColor?: string; backgroundColor?: string; placeholder?: string; + type?: string; + width?: string; onChange?(parameter: any | void): any | void; } @@ -15,7 +18,7 @@ const Input = styled.input` min-height: 50px; max-height: 50px; height: 50px; - width: 100%; + min-height: 50px; appearance: none; border: none; border-radius: 10px; @@ -31,6 +34,7 @@ const Input = styled.input` let backgroundColor = props.backgroundColor ? props.backgroundColor : "#263237"; + let width = props.width ? props.width : "100%"; return css` color: ${color}; font-size: ${fontSize}; @@ -39,26 +43,33 @@ const Input = styled.input` border: 1px solid ${activeHoverColor}; } background-color: ${backgroundColor}; + width: ${width}; `; }} `; export const CustomLoginInput: React.FC = ({ + value, color, fontSize, activeHoverColor, backgroundColor, placeholder, - onChange + type, + onChange, + width }) => { return ( ); }; diff --git a/client/src/presentation/components/atomic-reusable/global-header.tsx b/client/src/presentation/components/atomic-reusable/global-header.tsx index fa6fde46..abfcf476 100644 --- a/client/src/presentation/components/atomic-reusable/global-header.tsx +++ b/client/src/presentation/components/atomic-reusable/global-header.tsx @@ -1,13 +1,12 @@ -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import styled from "styled-components"; - import Dubu from "assets/dubu.png"; -import Notification from "assets/notification.png"; - import { CustomButton } from "./custom-button"; import { IconBox } from "./icon-box"; +import { ApplicationProptype } from "prop-types/application-type"; +import { Link } from "react-router-dom"; +import { InvitationAlarm } from "presentation/components/invitation-alarm"; -// 참고 : https://www.w3schools.com/css/tryit.asp?filename=trycss_dropdown_button const Wrapper = styled.header` display: flex; justify-content: space-between; @@ -27,19 +26,19 @@ const IconBoxWrapper = styled.section` const DropDown = styled.section` position: relative; display: inline-block; - - &:hover { - display: block; - > div { - display: block; - } - } `; -const ContentWrapper = styled.div` - display: none; +interface On { + toggle: boolean; +} + +const ContentWrapper = styled.section` + display: ${({ toggle }) => { + if (!toggle) return "none"; + return "block"; + }}; position: absolute; - transform: translateX(-90%); + transform: translateX(-80%); background-color: #f9f9f9; min-width: 160px; box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2); @@ -47,13 +46,9 @@ const ContentWrapper = styled.div` color: black; padding: 12px 16px; text-decoration: none; - &:hover { - background-color: #f1f1f1; - display: block; - } `; -const Content = styled.a` +const Content = styled.article` color: black; padding: 12px 16px; text-decoration: none; @@ -68,33 +63,59 @@ const Title = styled.section` font-size: 1.4rem; `; -export const GlobalHeader: React.FC = () => { - const [isLoggedIn, setIsLoggedIn] = useState("false"); +export const GlobalHeader: React.FC = ({ + Application +}) => { + const [isLoggedIn, setIsLoggedIn] = useState(false); + const [on, setOn] = useState(false); + + useEffect(() => { + setIsLoggedIn(Application.services.authService.isLogined()); + }); + + const clickDropdown = () => { + setOn(on === false); + }; + + const mouseLeave = () => { + if (on) setOn(false); + }; + + const logout = () => { + Application.services.authService.logout(); + window.location.href = "/"; + }; return ( - Snug + + Snug + {isLoggedIn ? ( - + - - 프로필 - Snug 만들기 - 로그아웃 + + 프로필 + + Snug 만들기 + + 로그아웃 - ) : ( - + + + )} + ); }; diff --git a/client/src/presentation/components/atomic-reusable/icon-box.tsx b/client/src/presentation/components/atomic-reusable/icon-box.tsx index cbfd74da..024052a6 100644 --- a/client/src/presentation/components/atomic-reusable/icon-box.tsx +++ b/client/src/presentation/components/atomic-reusable/icon-box.tsx @@ -4,20 +4,30 @@ import styled, { css } from "styled-components"; interface PropsType { imageSrc: string; size?: string; + borderRadius?: string; + backgroundColor?: string; onClick?(parameter: any | void): any | void; onKeyPress?(parameter: any | void): any | void; } + interface CustomImgBoxProps { size?: string; + borderRadius?: string; + backgroundColor?: string; } + const CustomImgBox = styled.section` display: flex; align-items: center; justify-content: center; - border-radius: 5px; + border-radius: ${props => (props.borderRadius ? props.borderRadius : "5px")}; margin: 5px; + min-width: ${props => (props.size ? props.size : "30px")}; + max-width: ${props => (props.size ? props.size : "30px")}; width: ${props => (props.size ? props.size : "30px")}; height: ${props => (props.size ? props.size : "30px")}; + background-color: ${props => + props.backgroundColor ? props.backgroundColor : ""}; &:hover { background-color: #39515a; } @@ -29,7 +39,12 @@ const CustomImg = styled.img` export const IconBox: React.FC = props => { return ( - + ); diff --git a/client/src/presentation/components/atomic-reusable/page-layout.tsx b/client/src/presentation/components/atomic-reusable/page-layout.tsx index 9e7e8b37..0b37365b 100644 --- a/client/src/presentation/components/atomic-reusable/page-layout.tsx +++ b/client/src/presentation/components/atomic-reusable/page-layout.tsx @@ -1,6 +1,7 @@ -import React from "react"; +import React, { Props } from "react"; import styled from "styled-components"; import { GlobalHeader } from "./global-header"; +import { ApplicationProptype } from "prop-types/application-type"; const Wrapper = styled.section` display: flex; @@ -15,10 +16,13 @@ const ContentsWrapper = styled.section` width: 100vw; `; -export const PageLayout: React.FC = ({ children }) => { +export const PageLayout: React.FC = ({ + children, + Application +}) => { return ( - + {children} ); diff --git a/client/src/presentation/components/invitation-alarm/index.tsx b/client/src/presentation/components/invitation-alarm/index.tsx new file mode 100644 index 00000000..925e22d2 --- /dev/null +++ b/client/src/presentation/components/invitation-alarm/index.tsx @@ -0,0 +1,183 @@ +import React, { useState, useCallback, useContext, useEffect } from "react"; +import styled from "styled-components"; +import { IconBox } from "presentation/components/atomic-reusable/icon-box"; +import { CustomButton } from "presentation/components/atomic-reusable/custom-button"; +import Notification from "assets/notification.png"; +import { globalApplication } from "contexts/application-context"; +import { Invite } from "core/entity/invite"; +import { globalSocket } from "contexts/socket-context"; + +const Wrapper = styled.section` + position: fixed; + right: 0; + bottom: 0; + height: 30%; + width: 28%; + display: flex; + justify-content: flex-end; + align-items: flex-end; +`; + +const DropDown = styled.section` + position: relative; + display: flex; + transform: translate(50px, -60px); + flex-direction: column; + transition: transform 300ms ease-in; + width: 100%; + height: 150px; + padding: 5px; + border-radius: 10px; + background-color: #9da1a5; + overflow-y: scroll; + &::-webkit-scrollbar { + width: 5px; + border-radius: 10px; + background: none; + background-color: #2a2d30; + } + &::-webkit-scrollbar-thumb { + background: #f8f7fb; + opacity: 0.4; + } + &::-webkit-scrollbar-track { + background: none; + } +`; + +const Buttons = styled.section` + display: flex; + justify-content: space-around; + width: 40%; +`; + +const DropDownMenu = styled.section` + background-color: #eae8e8; + color: #211d1d; + width: 100%; + display: flex; + justify-content: space-around; + border-radius: 10px; + margin-bottom: 3px; +`; + +const InvitationNumber = styled.span` + background-color: red; + color: #ffffff; + border-radius: 50px; + width: 20px; + height: 20px; + display: block; + text-align: center; + position: fixed; + right: 0; + bottom: 0; +`; + +export const InvitationAlarm: React.FC = () => { + const [onDropdown, setOnDropdown] = useState(false); + const [invitedSnugs, setInvitedSnugs] = useState([]); + + const application = useContext(globalApplication); + const socket = useContext(globalSocket); + + const user = application.services.authService.getUserInfo(); + + const toggleDropdown = useCallback(() => { + setOnDropdown(!onDropdown); + }, [onDropdown]); + + useEffect(() => { + const fetchInvitationLists = async () => { + if (!user.id) return; + const { + invitations + } = (await application.services.inviteService.getInvitedSnugs( + user.id + )) as any; + if (!invitations || invitations.length === 0) { + setInvitedSnugs([]); + return; + } + setInvitedSnugs(invitations as Invite[]); + }; + fetchInvitationLists(); + }, []); + + useEffect(() => { + const { userSocket } = socket; + userSocket.off("tellInvitation"); + const id = user.id; + userSocket.emit("login", { userId: id }); + userSocket.on("tellInvitation", (invitation: any) => { + const invitedSnug = invitation.payload; + const currentInvitation = invitedSnugs; + currentInvitation.push(invitedSnug); + setInvitedSnugs([...currentInvitation]); + }); + }, [invitedSnugs]); + + const acceptDeclineHandler = async ( + invitedSnugs: Invite[], + invitation: Invite, + agree: boolean + ) => { + const idx = invitedSnugs.indexOf(invitation); + invitedSnugs.splice(idx, 1); + setInvitedSnugs([...invitedSnugs]); + const result = (await application.services.inviteService.responseToInvitation( + invitation, + agree + )) as any; + window.location.href = result.snug.link!; + if (!result) return; + }; + + return ( + + {onDropdown && ( + + {invitedSnugs.map(invitation => ( + + {invitation.snug} + + + + + + ))} + + )} + {invitedSnugs.length} + + + ); +}; diff --git a/client/src/presentation/components/register-user/inputs/email-input.tsx b/client/src/presentation/components/register-user/inputs/email-input.tsx new file mode 100644 index 00000000..fa8978d3 --- /dev/null +++ b/client/src/presentation/components/register-user/inputs/email-input.tsx @@ -0,0 +1,58 @@ +import React from "react"; +import styled from "styled-components"; +import { CustomLoginInput } from "presentation/components/atomic-reusable/custom-login-input"; +import { CustomButton } from "presentation/components/atomic-reusable/custom-button"; +import { InputsPropTypes } from "./inputs-prop-types"; + +const InputFlex = styled.section` + display: flex; + align-items: center; + justify-content: space-between; +`; + +const Input = styled.section` + height: 100%; + display: flex; + flex-direction: column; +`; + +const WarningText = styled.span` + color: red; + width: 100%; + height: 10px; +`; + +export const EmailInput: React.FC = ({ + onChange, + isWarningOn, + onClick, + disabled, + disabledColor +}) => { + return ( + + + + + + {isWarningOn && 유효한 이메일 형식이 아닙니다.} + + ); +}; diff --git a/client/src/presentation/components/register-user/inputs/inputs-prop-types.tsx b/client/src/presentation/components/register-user/inputs/inputs-prop-types.tsx new file mode 100644 index 00000000..af0addfe --- /dev/null +++ b/client/src/presentation/components/register-user/inputs/inputs-prop-types.tsx @@ -0,0 +1,7 @@ +export interface InputsPropTypes { + onChange?(parameter: any | void): any | void; + isWarningOn?: boolean; + disabled?: boolean; + disabledColor?: string; + onClick?(parameter: any | void): any | void; +} diff --git a/client/src/presentation/components/register-user/inputs/name-input.tsx b/client/src/presentation/components/register-user/inputs/name-input.tsx new file mode 100644 index 00000000..782e82fe --- /dev/null +++ b/client/src/presentation/components/register-user/inputs/name-input.tsx @@ -0,0 +1,23 @@ +import React from "react"; +import styled from "styled-components"; +import { CustomLoginInput } from "presentation/components/atomic-reusable/custom-login-input"; +import { InputsPropTypes } from "./inputs-prop-types"; + +const Input = styled.section` + height: 100%; + display: flex; + flex-direction: column; +`; + +export const NameInput: React.FC = ({ onChange }) => { + return ( + + + + ); +}; diff --git a/client/src/presentation/components/register-user/inputs/password-check-input.tsx b/client/src/presentation/components/register-user/inputs/password-check-input.tsx new file mode 100644 index 00000000..068e98b7 --- /dev/null +++ b/client/src/presentation/components/register-user/inputs/password-check-input.tsx @@ -0,0 +1,34 @@ +import React from "react"; +import styled from "styled-components"; +import { CustomLoginInput } from "presentation/components/atomic-reusable/custom-login-input"; +import { InputsPropTypes } from "./inputs-prop-types"; + +const Input = styled.section` + height: 100%; + display: flex; + flex-direction: column; +`; + +const WarningText = styled.span` + color: red; + width: 100%; + height: 10px; +`; + +export const PasswordCheckInput: React.FC = ({ + onChange, + isWarningOn +}) => { + return ( + + + {isWarningOn && 비밀번호가 같지 않습니다.} + + ); +}; diff --git a/client/src/presentation/components/register-user/inputs/password-input.tsx b/client/src/presentation/components/register-user/inputs/password-input.tsx new file mode 100644 index 00000000..3cf60985 --- /dev/null +++ b/client/src/presentation/components/register-user/inputs/password-input.tsx @@ -0,0 +1,34 @@ +import React from "react"; +import styled from "styled-components"; +import { CustomLoginInput } from "presentation/components/atomic-reusable/custom-login-input"; +import { InputsPropTypes } from "./inputs-prop-types"; + +const Input = styled.section` + height: 100%; + display: flex; + flex-direction: column; +`; + +const WarningText = styled.span` + color: red; + width: 100%; + height: 10px; +`; + +export const PasswordInput: React.FC = ({ + onChange, + isWarningOn +}) => { + return ( + + + {isWarningOn && 비밀번호는 8자 이상입니다.} + + ); +}; diff --git a/client/src/presentation/components/register-user/modal/index.tsx b/client/src/presentation/components/register-user/modal/index.tsx new file mode 100644 index 00000000..91993e39 --- /dev/null +++ b/client/src/presentation/components/register-user/modal/index.tsx @@ -0,0 +1,48 @@ +import React from "react"; +import styled from "styled-components"; +import { CustomButton } from "presentation/components/atomic-reusable/custom-button"; + +const Wrapper = styled.section` + position: absolute; + z-index: 1; + background-color: grey; + opacity: 0.9; + color: white; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-around; + width: 20%; + height: 15%; + top: 50%; + border-radius: 10px; + transform: translateY(-50%); +`; + +const content = styled.main` + margin-bottom: 10px; +`; + +interface PropTypes { + onClick?(parameter: any | void): any | void; + message?: string; +} + +export const Modal: React.FC = ({ onClick, message }) => { + return ( + +
{message}
+ +
+ ); +}; diff --git a/client/src/presentation/components/snug/channel-browse-modal/channel-browse-modal-item.tsx b/client/src/presentation/components/snug/channel-browse-modal/channel-browse-modal-item.tsx index 1fabe64a..55fc4c42 100644 --- a/client/src/presentation/components/snug/channel-browse-modal/channel-browse-modal-item.tsx +++ b/client/src/presentation/components/snug/channel-browse-modal/channel-browse-modal-item.tsx @@ -1,9 +1,18 @@ -import React from "react"; +import React, { useState } from "react"; import styled from "styled-components"; +import { ApplicationProptype } from "prop-types/application-type"; +import { RouteComponentProps } from "react-router"; +import { + usePathParameterDispatch, + usePathParameter +} from "contexts/path-parameter-context"; +import { useModalToggledDispatch } from "contexts/modal-context"; const Wrapper = styled.section` + position: relative; display: flex; width: 100%; + height: 60px; color: ${({ theme }) => theme.snugSubFont}; flex-direction: column; border-top: 1px solid ${({ theme }) => theme.snugBorderColor}; @@ -30,23 +39,74 @@ const Footer = styled.footer` margin-left: 10px; `; +const Button = styled.button.attrs({ + id: "join--button" +})<{ on: boolean }>` + display: ${({ on }) => (on ? "" : "none")}; + position: absolute; + box-sizing: content-box; + right: 10px; + top: 50%; + transform: translateY(-50%); + width: 35px; + height: 20px; + background-color: #00b20090; + border: none; + border-radius: 5px; + font-size: 9pt; + font-weight: bold; + color: white; +`; + interface ChannelBrowseModal { title?: string; + id?: number; description?: string; privacy?: boolean; user?: string; createdAt?: Date; } -export const ChannelBrowseModalItem: React.FC = props => { +export const ChannelBrowseModalItem: React.FC = props => { + const [on, setOn] = useState(false); + const { history, id } = props; + const pathParameter = usePathParameter(); + const pathPatameterDispatch = usePathParameterDispatch(); + const ModalToggle = useModalToggledDispatch(); + + function enter() { + setOn(true); + } + + function leave() { + setOn(false); + } + + function moveChannel() { + pathPatameterDispatch({ + type: "IN", + channelId: id! + }); + history.push(`/snug/${pathParameter.snugId}/channel/id`); + + ModalToggle!({ + type: "TOGGLE_CHANNEL_BROWSE_MODAL" + }); + } + return ( - +
{props.title}
{props.description}
Created by {props.user} on{" "} {props.createdAt && props.createdAt.toLocaleString()}
+
); }; diff --git a/client/src/presentation/components/snug/channel-browse-modal/channel-browse-modal-sort-list.tsx b/client/src/presentation/components/snug/channel-browse-modal/channel-browse-modal-sort-list.tsx index 34167d16..b404fec6 100644 --- a/client/src/presentation/components/snug/channel-browse-modal/channel-browse-modal-sort-list.tsx +++ b/client/src/presentation/components/snug/channel-browse-modal/channel-browse-modal-sort-list.tsx @@ -4,6 +4,8 @@ import { useChannels, Channels } from "contexts/channel-context"; import { ChannelBrowseModalItem } from "./channel-browse-modal-item"; import { Channel } from "core/entity/channel"; import styled from "styled-components"; +import { ApplicationProptype } from "prop-types/application-type"; +import { RouteComponentProps } from "react-router"; interface Criterion { DisplayType: DisplayType; @@ -56,7 +58,9 @@ const filterPrivateChannels = (channels: Channels, props: DisplayType) => { return null; }; -export const ChannelBrowseModalSortList: React.FC = props => { +export const ChannelBrowseModalSortList: React.FC = props => { const channels = useChannels(); const sortChannels = () => { @@ -76,7 +80,9 @@ export const ChannelBrowseModalSortList: React.FC = props => { sortChannels()!.map(channel => { return ( { +export const ChannelBrowseModal: React.FC = props => { const [selectedDisplayType, setSelectedDisplayType] = useState( DisplayType.all ); @@ -78,6 +76,7 @@ export const ChannelBrowseModal: React.FC = () => { setSelectedSortType={setSelectedSortType} /> diff --git a/client/src/presentation/components/snug/channel-list/channel-title.tsx b/client/src/presentation/components/snug/channel-list/channel-title.tsx index 30160bd2..e5d39c54 100644 --- a/client/src/presentation/components/snug/channel-list/channel-title.tsx +++ b/client/src/presentation/components/snug/channel-list/channel-title.tsx @@ -48,7 +48,11 @@ export const ChannelTitle: React.FC = props => { const { history, match, id } = props; useEffect(() => { - history.push(`/snug/${pathParameter.channelId}`); + history.push( + `/snug/${pathParameter.snugId}/channel/${ + pathParameter.channelId ? pathParameter.channelId : 0 + }` + ); if (pathParameter.channelId == id) return setOn(true); setOn(false); }, [pathParameter]); diff --git a/client/src/presentation/components/snug/channel-list/index.tsx b/client/src/presentation/components/snug/channel-list/index.tsx index dacb5028..f1daf649 100644 --- a/client/src/presentation/components/snug/channel-list/index.tsx +++ b/client/src/presentation/components/snug/channel-list/index.tsx @@ -7,6 +7,10 @@ import { match } from "react-router"; import { ChannelMatchType } from "prop-types/channel-match-type"; import { History } from "history"; import { Context } from "context.instance"; +import { + usePathParameter, + usePathParameterDispatch +} from "contexts/path-parameter-context"; const Wrapper = styled.section` padding: 10px 0px; @@ -14,24 +18,32 @@ const Wrapper = styled.section` interface PropTypes { match: match; - socket: SocketIO.Server; history: History; Application: Context; } export const ChannelList: React.FC = ({ match, - socket, history, Application }) => { const channels = useChannels(); const dispatch = useChannelDispatch(); + const pathParameters = usePathParameter(); + const pathParameterDispatch = usePathParameterDispatch(); + + useEffect(() => { + pathParameterDispatch({ + type: "GETSNUGID", + snugId: Number(match.params.snugId) + }); + }, []); useEffect(() => { - if (!match.params.channelId) socket.emit("join", match.params.channelId); (async function() { - const channel = await Application.services.channelService.getChannelList(); + const channel = await Application.services.channelService.getChannelList( + Number(match.params.snugId) + ); if (typeof channel === "boolean" || !dispatch) return; dispatch({ type: "MULTI", diff --git a/client/src/presentation/components/snug/channel-plus-modal/channel-plus-modal-contents.tsx b/client/src/presentation/components/snug/channel-plus-modal/channel-plus-modal-contents.tsx index fd00fa8e..ab2e72af 100644 --- a/client/src/presentation/components/snug/channel-plus-modal/channel-plus-modal-contents.tsx +++ b/client/src/presentation/components/snug/channel-plus-modal/channel-plus-modal-contents.tsx @@ -6,6 +6,7 @@ import { CustomOnOffButton } from "presentation/components/atomic-reusable/custo import { useChannelDispatch } from "contexts/channel-context"; import { useModalToggledDispatch } from "contexts/modal-context"; import { ApplicationProptype } from "prop-types/application-type"; +import { usePathParameter } from "contexts/path-parameter-context"; const ContentsForm = styled.form` display: flex; @@ -51,11 +52,13 @@ export const ChannelPlusModalContents: React.FC = ({ const channelDispatch = useChannelDispatch(); const modalDispatch = useModalToggledDispatch(); + const parameter = usePathParameter(); const submitHandler = async (event: React.FormEvent) => { event.preventDefault(); - + const result = await Application.services.channelService.create( + parameter.snugId!, title, description, privacy diff --git a/client/src/presentation/components/snug/chat-container/index.tsx b/client/src/presentation/components/snug/chat-container/index.tsx index 7a04bb10..57ab3482 100644 --- a/client/src/presentation/components/snug/chat-container/index.tsx +++ b/client/src/presentation/components/snug/chat-container/index.tsx @@ -1,24 +1,36 @@ -import React, { useEffect } from "react"; -import styled from "styled-components"; +import React, { useEffect, useContext } from "react"; +import styled, { css } from "styled-components"; import { useMessages, useMessagesDispatch } from "contexts/messages-context"; -import { AppSocketChannelMatchProps } from "prop-types/match-extends-types"; +import { ChannelRouteComponentType } from "prop-types/channel-match-type"; import { PostCard } from "presentation/components/snug/post-card"; import { Post } from "core/entity/post"; import { usePathParameter } from "contexts/path-parameter-context"; +import { globalApplication } from "contexts/application-context"; -const ChatContentWrapper = styled.section` - height: 100%; +const ChatContentWrapper = styled.section.attrs({ + id: "scroll" +})<{ isParticipated: boolean }>` + min-height: ${({ isParticipated }) => + isParticipated ? css`calc(100% - 75px)` : css`calc(100% - 150px)`}; + max-height: ${({ isParticipated }) => + isParticipated ? css`calc(100% - 75px)` : css`calc(100% - 150px)`}; width: 100%; + overflow-y: auto; display: flex; - flex-direction: column; - justify-content: flex-end; + flex-flow: column nowrap; `; -export const ChatContent: React.FC = props => { - const { Application } = props; +const Wrapper = styled.section.attrs({})` + margin-top: auto !important; +`; + +export const ChatContent: React.FC = props => { + const { isParticipated } = props; + const application = useContext(globalApplication); const posts: Post[] = useMessages(); const dispatch = useMessagesDispatch(); - const { socket } = props; const pathParameter = usePathParameter(); useEffect(() => { @@ -26,11 +38,10 @@ export const ChatContent: React.FC = props => { dispatch({ type: "CLEAR_ALL" }); - const resultPosts = await Application.services.postService.getList( - pathParameter.channelId + const resultPosts = await application.services.postService.getList( + pathParameter.channelId! ); if (typeof resultPosts == "boolean") return; - console.log(resultPosts); dispatch({ type: "MULTI_INPUT", posts: resultPosts @@ -38,6 +49,11 @@ export const ChatContent: React.FC = props => { })(); }, [pathParameter]); + useEffect(() => { + const obj: HTMLElement = document.getElementById("scroll")!; + obj.scrollTop = obj.scrollHeight; + }, [posts]); + function messageList(): React.ReactNode { if (!posts) return <>; return posts!.map((post: Post) => ( @@ -51,5 +67,9 @@ export const ChatContent: React.FC = props => { )); } - return {messageList()}; + return ( + + {messageList()} + + ); }; diff --git a/client/src/presentation/components/snug/chat-input-box/index.tsx b/client/src/presentation/components/snug/chat-input-box/index.tsx index 9a5cfbec..e78c727a 100644 --- a/client/src/presentation/components/snug/chat-input-box/index.tsx +++ b/client/src/presentation/components/snug/chat-input-box/index.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from "react"; +import React, { useState, useEffect, useContext } from "react"; import styled from "styled-components"; import ClipWhite from "assets/clip-white.png"; import AtWhite from "assets/at-white.png"; @@ -6,13 +6,17 @@ import FaceWhite from "assets/face-white.png"; import { IconBox } from "presentation/components/atomic-reusable/icon-box"; import { useMessagesDispatch, useMessages } from "contexts/messages-context"; import dubu from "assets/dubu.png"; -import { AppSocketChannelMatchProps } from "prop-types/match-extends-types"; import { ResponseEntity } from "data/http/api/response/ResponseEntity"; import { Post } from "core/entity/post"; import { usePathParameter } from "contexts/path-parameter-context"; +import { globalSocket } from "contexts/socket-context"; +import { globalApplication } from "contexts/application-context"; +import { AppChannelMatchProps } from "prop-types/match-extends-types"; + const InputWrapper = styled.section` width: 100%; - height: 75px; + min-height: 75px; + max-height: 75px; background-color: ${({ theme }) => theme.snug}; padding-top: 10px; padding-bottom: 20px; @@ -54,16 +58,21 @@ const StyledInput = styled.input.attrs({ } `; -export const ChatInputBox: React.FC = ({ - Application, - socket -}) => { +interface PropType extends AppChannelMatchProps { + openModal: () => void; +} + +export const ChatInputBox: React.FC = props => { + const { Application, openModal } = props; + const application = useContext(globalApplication); + const KEY_PRESS_EVENT_KEY = "Enter"; const [message, setMessage] = useState(""); const [id, setId] = useState(0); - const messages = useMessages(); const dispatch = useMessagesDispatch(); const pathPrameter = usePathParameter(); + const { snugSocket } = useContext(globalSocket); + const inputChangeEventHandler = ( event: React.ChangeEvent ) => { @@ -71,22 +80,23 @@ export const ChatInputBox: React.FC = ({ }; useEffect(() => { - socket.on("newPost", (resultData: ResponseEntity) => { - console.log("(성공)"); + snugSocket.off("newPost"); + snugSocket.on("newPost", (resultData: ResponseEntity) => { const { payload } = resultData; + if (payload.room != pathPrameter.channelId) return; dispatch({ type: "CREATE", id: payload.id!, profile: { name: payload.profile!.name! || "두부", - thumbnail: dubu + thumbnail: payload.profile!.thumbnail! }, createdAt: payload.createdAt!, updatedAt: payload.updatedAt!, contents: payload.contents! }); }); - }, []); + }, [pathPrameter]); //이 부분은 mock 데이터로 되어 있으니 차후 수정이 필요함 const inputKeyPressEventHandler = async ( @@ -97,10 +107,10 @@ export const ChatInputBox: React.FC = ({ if (!message.trim()) return; if (!dispatch) return; - const result = await Application.services.postService.createMessage( + const result = await application.services.postService.createMessage( 1, message, - pathPrameter.channelId + pathPrameter.channelId! ); if (!result) return; setId(id + 1); @@ -111,7 +121,7 @@ export const ChatInputBox: React.FC = ({ - + = props => { + const { file } = props; + const [previewUrl, setPreviewUrl] = useState(""); + + const reader = new FileReader(); + reader.readAsDataURL(file); + reader.onloadend = () => { + setPreviewUrl(reader.result as string); + }; + + return ; +}; diff --git a/client/src/presentation/components/snug/file-preview/index.tsx b/client/src/presentation/components/snug/file-preview/index.tsx new file mode 100644 index 00000000..d3d1d0cc --- /dev/null +++ b/client/src/presentation/components/snug/file-preview/index.tsx @@ -0,0 +1,38 @@ +import React, { useState } from "react"; +import { NormalPreview } from "./normal-preview"; +import { ImagePreview } from "./image-preview"; +import styled from "styled-components"; + +interface PropTypes { + file: File; +} + +const Container = styled.div` + display: flex; + align-items: center; + justify-content: center; + color: ${({ theme }) => theme.snugMainFont}; + height: auto; + border: 1px solid ${({ theme }) => theme.snugBorderColor}; + border-radius: 0.5rem; + box-sizing: border-box; +`; + +function isImage(fileName: string) { + if (/\.(gif|jpg|jpeg|tiff|png)$/i.test(fileName)) return true; + return false; +} + +export const FilePreview: React.FC = props => { + const { file } = props; + + return ( + + {isImage(file.name) ? ( + + ) : ( + + )} + + ); +}; diff --git a/client/src/presentation/components/snug/file-preview/normal-preview.tsx b/client/src/presentation/components/snug/file-preview/normal-preview.tsx new file mode 100644 index 00000000..81293b19 --- /dev/null +++ b/client/src/presentation/components/snug/file-preview/normal-preview.tsx @@ -0,0 +1,25 @@ +import React, { Fragment } from "react"; +import styled from "styled-components"; + +interface PropTypes { + file: File; +} + +const CustomPreview = styled.div` + margin: 1rem; + padding: 1rem; + color: ${({ theme }) => theme.snugSubFont}; + background: ${({ theme }) => theme.snug}; + border-radius: 1rem; +`; + +export const NormalPreview: React.FC = props => { + const { file } = props; + + return ( + +
이름: {file.name}
+
크기: {file.size} Bytes
+
+ ); +}; diff --git a/client/src/presentation/components/snug/file-upload-modal/file-drop-area.tsx b/client/src/presentation/components/snug/file-upload-modal/file-drop-area.tsx new file mode 100644 index 00000000..e9567dcf --- /dev/null +++ b/client/src/presentation/components/snug/file-upload-modal/file-drop-area.tsx @@ -0,0 +1,67 @@ +import React, { CSSProperties, useState } from "react"; +import styled from "styled-components"; + +const Wrapper = styled.div` + width: 100%; + height: 100px; + margin: 0 auto; + color: ${({ theme }) => theme.snugMainFont}; + background: ${({ theme }) => theme.snug}; + border: 1px solid ${({ theme }) => theme.snugBorderColor}; + display: flex; + border-radius: 0.5rem; + align-items: center; + justify-content: center; + margin-bottom: 1rem; + cursor: pointer; +`; + +const InfoMessage = styled.span` + color: #888; +`; + +const isHighLight: CSSProperties = { + background: "#ccc" +}; + +interface PropTypes { + setFile: React.Dispatch>; +} + +export const FileDropArea: React.FC = props => { + const [isDragging, setDragging] = useState(false); + const { setFile } = props; + + const onDragOver: (event: React.DragEvent) => void = ( + event: React.DragEvent + ) => { + event.preventDefault(); + setDragging(true); + }; + + const onDrop: (event: React.DragEvent) => void = ( + event: React.DragEvent + ) => { + event.preventDefault(); + + setDragging(false); + props.setFile(event.dataTransfer.files[0]); + }; + + const onDragLeave: (event: React.DragEvent) => void = ( + event: React.DragEvent + ) => { + setDragging(false); + }; + + return ( + + Drop your file here + + ); +}; diff --git a/client/src/presentation/components/snug/file-upload-modal/index.tsx b/client/src/presentation/components/snug/file-upload-modal/index.tsx new file mode 100644 index 00000000..6f0c2382 --- /dev/null +++ b/client/src/presentation/components/snug/file-upload-modal/index.tsx @@ -0,0 +1,146 @@ +import React, { useState } from "react"; +import styled from "styled-components"; +import { CustomButton } from "presentation/components/atomic-reusable/custom-button"; +import { FileDropArea } from "./file-drop-area"; +import { FilePreview } from "../file-preview"; + +const Modal = styled.div` + position: fixed; + z-index: 1; + left: 0; + top: 0; + width: 100%; + height: 100%; + overflow: auto; + background-color: rgb(0, 0, 0); + background-color: rgba(0, 0, 0, 0.4); +`; + +const ModalContent = styled.div` + position: relative; + height: auto; + background-color: ${({ theme }) => theme.snug}; + margin: 10% auto; + padding: 20px; + border: 1px solid black; + border-radius: 1rem; + width: 30%; + box-sizing: border-box; +`; + +const ModalHeader = styled.header` + padding: 1rem; + font-size: 200%; + font-weight: bold; + color: white; + box-sizing: border-box; +`; + +const ModalBody = styled.body` + padding: 1rem; + box-sizing: border-box; +`; + +const ModalFooter = styled.footer` + display: flex; + justify-content: flex-end; + padding: 1rem; + box-sizing: border-box; +`; + +const CloseButton = styled.span` + color: #aaa; + float: right; + font-size: 28px; + font-weight: bold; + &:hover, + &:focus { + color: black; + text-decoration: none; + cursor: pointer; + } +`; + +const CustomInput = styled.section` + width: 100%; + border: 1px solid ${({ theme }) => theme.snugBorderColor}; + background-color: ${({ theme }) => theme.snug}; + border-radius: 0.5rem; + overflow: hidden; + display: flex; + align-items: center; + padding: 5px; + box-sizing: border-box; + margin-bottom: 2rem; +`; + +const StyledInput = styled.textarea.attrs({ + placeholder: "메세지를 입력하세요." +})` + --webkit-appearance: none; + background-color: ${({ theme }) => theme.snug}; + font-size: 14px; + color: #e3e3e3; + width: 100%; + border: none; + box-sizing: border-box; + &:active, + :focus { + outline: none; + } +`; + +const HiddenInput = styled.input.attrs({ + type: "file" +})` + display: none; +`; + +interface PropTypes { + closeModal: () => void; +} + +export const FileUploadModal: React.FC = props => { + const [file, setFile] = useState(new File([], "")); + const onChange: (event: React.ChangeEvent) => void = ( + event: React.ChangeEvent + ) => { + event.preventDefault(); + setFile(event.target.files![0]); + }; + + return ( + + + + × + 파일 업로드 + + + + + + + + + + {file.size > 0 ? : undefined} + + + + + + + + ); +}; diff --git a/client/src/presentation/components/snug/modals/index.tsx b/client/src/presentation/components/snug/modals/index.tsx index 1448af0e..864013b0 100644 --- a/client/src/presentation/components/snug/modals/index.tsx +++ b/client/src/presentation/components/snug/modals/index.tsx @@ -3,16 +3,18 @@ import { ChannelPlusModal } from "presentation/components/snug/channel-plus-moda import { ChannelBrowseModal } from "presentation/components/snug/channel-browse-modal"; import { useModalToggled } from "contexts/modal-context"; import { ApplicationProptype } from "prop-types/application-type"; +import { RouteComponentProps } from "react-router"; -export const Modals: React.FC = ({ Application }) => { +export const Modals: React.FC = props => { const modalsContext = useModalToggled(); return ( <> {modalsContext && modalsContext.ChannelBrowseModal && ( - + )} - + ); }; diff --git a/client/src/presentation/components/snug/preview/index.tsx b/client/src/presentation/components/snug/preview/index.tsx new file mode 100644 index 00000000..11354be8 --- /dev/null +++ b/client/src/presentation/components/snug/preview/index.tsx @@ -0,0 +1,88 @@ +import React, { useContext } from "react"; +import styled, { css } from "styled-components"; +import { globalApplication } from "contexts/application-context"; +import { usePathParameter } from "contexts/path-parameter-context"; +import { AppChannelMatchProps } from "prop-types/match-extends-types"; + +type PropsType = { + setIsParticipated: React.Dispatch>; +}; + +export const Preview: React.FC = props => { + const Application = useContext(globalApplication); + const pathParameter = usePathParameter(); + const { setIsParticipated } = props; + + async function join() { + const result = await Application.services.channelService.join( + pathParameter.channelId! + ); + setIsParticipated(result); + } + + return ( + +
+

이 채널은 블라블라

+

블라블라블라블라블라블라블라

+
+ 참가하기 + 나가기 +
+ ); +}; + +const PreviewWrrapper = styled.section` + width: 100%; + min-height: 150px; + max-height: 150px; + background-color: ${({ theme }) => theme.snugHover}; + color: ${({ theme }) => theme.snugMainFont}; + padding-top: 10px; + padding-bottom: 20px; + box-sizing: border-box; + text-align: center; +`; + +const StyledButton = css` + box-sizing: border-box; + width: 90px; + height: 30px; + font-size: 12pt; + padding: 0px; + margin: 0px 10px; + color: inherit; + border: none; + border-radius: 5px; +`; + +const StyledJoinButton = styled.button` + ${StyledButton} + background-color: ${({ theme }) => theme.mainButtonColor}; + &:hover { + background-color: ${({ theme }) => theme.mainButtonColorHover}; + } +`; + +const StyledBackButton = styled.button` + ${StyledButton} + background-color: ${({ theme }) => theme.subButtonColor}; + &:hover { + background-color: ${({ theme }) => theme.subButtonColorHover}; + color: black; + } +`; + +const H1 = styled.h1` + font-size: 21pt; + margin: 10px 0; + font-weight: bold; +`; + +const P = styled.p` + display: inline-block; + margin: 0; + margin-bottom: 20px; + font-size: 10pt; + font-weight: 500; +`; diff --git a/client/src/presentation/pages/home/home-detail-snug.tsx b/client/src/presentation/pages/home/home-detail-snug.tsx index 6fca4402..eca17dc4 100644 --- a/client/src/presentation/pages/home/home-detail-snug.tsx +++ b/client/src/presentation/pages/home/home-detail-snug.tsx @@ -31,7 +31,7 @@ const Description = styled.section` justify-content: space-between; `; -const Title = styled.header` +const Name = styled.header` font-size: 1.5rem; font-weight: bold; `; @@ -53,18 +53,24 @@ const Square = styled.section` } `; -export const HomeDetailSnug: React.FC = () => { +interface PropTypes { + name: string; + description: string; + link: number; +} + +export const HomeDetailSnug: React.FC = (props) => { return ( - 우리 동네 축구팀 -
football.snug.com
+ {props.name} +
{props.description}
- + { - const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; - return re.test(email); -}; - -export const HomeForm: React.FC = () => { +export const HomeForm: React.FC = (props) => { + const { Application } = props; const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [validEmail, setValidEmail] = useState(true); - const handleOnChange = (event: React.ChangeEvent) => { + const onChangeEmail = (event: React.ChangeEvent) => { setEmail(event.target.value); setValidEmail(validateEmail(event.target.value)); }; + const onChangePassword = (event: React.ChangeEvent) => { + setPassword(event.target.value); + }; + + const login = async () => { + const result = await Application.services.authService.login( + email, + password + ); + console.log(result); + if (!result) { + setEmail(""); + setPassword(""); + return; + } + window.location.reload(); + }; + return ( @@ -66,10 +83,11 @@ export const HomeForm: React.FC = () => { {!validEmail && ( 유효한 이메일 형식이 아닙니다. @@ -77,15 +95,17 @@ export const HomeForm: React.FC = () => { { fontColor={"#ffffff"} fontWeight={"bold"} height={"auto"} + onClick={login} > diff --git a/client/src/presentation/pages/home/home-snug.tsx b/client/src/presentation/pages/home/home-snug.tsx index 5a29e3c9..088bf6c4 100644 --- a/client/src/presentation/pages/home/home-snug.tsx +++ b/client/src/presentation/pages/home/home-snug.tsx @@ -1,6 +1,9 @@ -import React from "react"; +import React, { useContext, useEffect, useState } from "react"; import styled from "styled-components"; +import { ApplicationProptype } from "prop-types/application-type"; import { HomeDetailSnug } from "./home-detail-snug"; +import { Snug } from "core/entity/snug"; +import { globalSocket } from "contexts/socket-context"; const Wrapper = styled.section` background-color: #ffffff; @@ -28,7 +31,7 @@ const DetailSnugWrapper = styled.section` width: 40%; display: flex; flex-direction: column; - align-contents: center; + align-content: center; border: 1px solid black; border-radius: 10px; padding: 10px; @@ -39,7 +42,32 @@ const Title = styled.header` font-size: 1.25rem; `; -export const HomeSnug: React.FC = () => { +export const HomeSnug: React.FC = props => { + const { Application } = props; + const [snugs, setSnugs] = useState([]); + const socket = useContext(globalSocket); + + useEffect(() => { + (async () => { + const initialSnugs = await Application.services.snugService.getList(); + setSnugs(initialSnugs); + })(); + }, []); + + useEffect(() => { + const { userSocket } = socket; + + userSocket.off("acceptInvitation"); + const user = Application.services.authService.getUserInfo(); + const id = user.id; + userSocket.emit("login", { userId: id }); + userSocket.on("acceptInvitation", (invitation: any) => { + const invitedSnug = invitation.payload; + const currentSnugs = snugs as Snug[]; + setSnugs(currentSnugs.concat(invitedSnug)); + }); + }); + return ( @@ -47,11 +75,18 @@ export const HomeSnug: React.FC = () => { 내 Snug - - - - - + {snugs + ? (snugs as Snug[]).map((snug: Snug) => { + return ( + + ); + }) + : undefined} ); diff --git a/client/src/presentation/pages/home/index.tsx b/client/src/presentation/pages/home/index.tsx index b2734056..420d7b18 100644 --- a/client/src/presentation/pages/home/index.tsx +++ b/client/src/presentation/pages/home/index.tsx @@ -1,10 +1,19 @@ -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import { PageLayout } from "presentation/components/atomic-reusable/page-layout"; import { HomeForm } from "./home-form"; import { HomeSnug } from "./home-snug"; +import { ApplicationProptype } from "prop-types/application-type"; -export const Home: React.FC = () => { +export const Home: React.FC = ({ Application }) => { const [isLoggedIn, setIsLoggedIn] = useState(false); - return {isLoggedIn ? : }; + useEffect(() => { + setIsLoggedIn(Application.services.authService.isLogined()); + }); + + return ( + + {isLoggedIn ? : } + + ); }; diff --git a/client/src/presentation/pages/invite-users/container/index.tsx b/client/src/presentation/pages/invite-users/container/index.tsx new file mode 100644 index 00000000..1ef8ab9d --- /dev/null +++ b/client/src/presentation/pages/invite-users/container/index.tsx @@ -0,0 +1,23 @@ +import React from "react"; +import styled from "styled-components"; +import { InviteDescription } from "presentation/pages/invite-users/description"; +import { InviteForm } from "presentation/pages/invite-users/form"; +import { AppInviteMatchProps } from "prop-types/match-extends-types"; + +const Wrapper = styled.section` + background-color: #ffffff; + height: 100%; + width: 100%; + display: flex; + align-items: center; + flex-direction: column; +`; + +export const InviteUsersContainer: React.FC = props => { + return ( + + + + + ); +}; diff --git a/client/src/presentation/pages/invite-users/description/index.tsx b/client/src/presentation/pages/invite-users/description/index.tsx new file mode 100644 index 00000000..d164f23d --- /dev/null +++ b/client/src/presentation/pages/invite-users/description/index.tsx @@ -0,0 +1,22 @@ +import React from "react"; +import styled from "styled-components"; + +const DescriptionWrapper = styled.section` + height: 20%; + display: flex; + align-items: center; +`; + +const Index = styled.span` + color: #000000; + font-weight: bold; + font-size: 2rem; +`; + +export const InviteDescription: React.FC = () => { + return ( + + 초대하기 + + ); +}; \ No newline at end of file diff --git a/client/src/presentation/pages/invite-users/form/Invite-button.tsx b/client/src/presentation/pages/invite-users/form/Invite-button.tsx new file mode 100644 index 00000000..33ff2d9f --- /dev/null +++ b/client/src/presentation/pages/invite-users/form/Invite-button.tsx @@ -0,0 +1,50 @@ +import React from "react"; +import styled from "styled-components"; +import {CustomButton} from "presentation/components/atomic-reusable/custom-button"; + +const Wrapper = styled.section` + display: flex; + flex-direction: column; +`; + +const ButtonWrapper = styled.section` + flex: 1 + margin-top: 1rem; +`; + +interface PropType { + sendEmails(parameter: any | void): any | void; + snugId: string; +} + +export const InviteButton: React.FC = ({sendEmails, snugId}) => { + const goHome = (event: React.MouseEvent) => { + event.preventDefault(); + window.location.assign(`/snug/${snugId}`); + }; + + return ( + + + + + + + + + ); +}; diff --git a/client/src/presentation/pages/invite-users/form/index.tsx b/client/src/presentation/pages/invite-users/form/index.tsx new file mode 100644 index 00000000..e40c02de --- /dev/null +++ b/client/src/presentation/pages/invite-users/form/index.tsx @@ -0,0 +1,33 @@ +import styled from "styled-components"; +import React, { useState } from "react"; +import { InviteUsers } from "presentation/pages/invite-users/form/invite-users"; +import { InviteButton } from "presentation/pages/invite-users/form/Invite-button"; +import { EmailModel } from "core/model/email-model"; +import { AppInviteMatchProps } from "prop-types/match-extends-types"; + +const Form = styled.form` + display: flex; + flex-direction: column; + height: 100%; + width: 40%; +`; + +export const InviteForm: React.FC = ({ + match, + Application +}) => { + const [emails, changeEmails] = useState([]); + const { snugId } = match.params; + if (!snugId) return null; + const sendEmails = (event: React.MouseEvent) => { + event.preventDefault(); + Application.services.inviteService.send(snugId, emails); + window.location.assign(`/snug/${snugId}`); + }; + return ( +
+ + + + ); +}; diff --git a/client/src/presentation/pages/invite-users/form/invite-users.tsx b/client/src/presentation/pages/invite-users/form/invite-users.tsx new file mode 100644 index 00000000..f0fd59bd --- /dev/null +++ b/client/src/presentation/pages/invite-users/form/invite-users.tsx @@ -0,0 +1,87 @@ +import styled from "styled-components"; +import React, {Dispatch, useState} from "react"; +import {CustomInput} from "presentation/components/atomic-reusable/custom-input"; +import {CustomButton} from "presentation/components/atomic-reusable/custom-button"; +import {EmailModel} from "core/model/email-model"; +import {ArrayHelper} from "core/utility/array-helper"; +import {pipe} from "core/utility/compose-helper"; + +const InputWrapper = styled.section` + width: 100%; + display: flex; + flex-direction: column; + background-color: #f4f4f4; + padding: 10px; + height: auto; +`; + +const ButtonWrapper = styled.section` + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + margin-top: 1rem; +`; + +const addEmailModel = (emails: EmailModel[], changeEmails: any) => { + const emailModel = new EmailModel(emails.length); + emails.push(emailModel); + changeEmails(emails); + return emailModel; +}; + +const createChangeHandler = (email: EmailModel) => { + return (event: React.MouseEvent) => { + email.changeEmail(event.toString()) + }; +}; + +const createCustomInput = (email: EmailModel) => { + const changeHandler = createChangeHandler(email); + return ; +}; + +const generateEmailContainer = pipe(addEmailModel, createCustomInput); + +const generateDefaultEmailContainers = (emails: EmailModel[], changeEmails: any) => { + const defaultEmailCount = 3; + return ArrayHelper.generateUntil(defaultEmailCount) + .map(() => generateEmailContainer(emails, changeEmails)); +}; + +const initializeEmailContainers = (emails: EmailModel[], changeEmails: Dispatch) => { + return ArrayHelper.hasNot(emails) ? generateDefaultEmailContainers(emails, changeEmails) : []; +}; + +interface PropType { + emails: EmailModel[]; + changeEmails(parameter: any | void): any | void; +} + +export const InviteUsers: React.FC = ({emails, changeEmails}) => { + const defaultEmails = initializeEmailContainers(emails, changeEmails); + const [emailContainers, addEmailContainers] = useState(defaultEmails); + const addEmailContainerHandler = (event: React.MouseEvent) => { + event.preventDefault(); + const emailContainer = generateEmailContainer(emails, changeEmails); + addEmailContainers(emailContainers.concat(emailContainer)); + }; + return ( + {emailContainers} + + + + ); +}; \ No newline at end of file diff --git a/client/src/presentation/pages/invite-users/index.tsx b/client/src/presentation/pages/invite-users/index.tsx new file mode 100644 index 00000000..7e73e51c --- /dev/null +++ b/client/src/presentation/pages/invite-users/index.tsx @@ -0,0 +1,13 @@ +import React from "react"; +import { PageLayout } from "presentation/components/atomic-reusable/page-layout"; +import { InviteUsersContainer } from "./container"; +import { AppInviteMatchProps } from "prop-types/match-extends-types"; + +export const InviteUsers: React.FC = props => { + const { Application } = props; + return ( + + + + ); +}; diff --git a/client/src/presentation/pages/register-snug/index.tsx b/client/src/presentation/pages/register-snug/index.tsx index 58f08a69..cd5a14dd 100644 --- a/client/src/presentation/pages/register-snug/index.tsx +++ b/client/src/presentation/pages/register-snug/index.tsx @@ -1,11 +1,15 @@ import React from "react"; import { PageLayout } from "presentation/components/atomic-reusable/page-layout"; import { RegisterSnugForm } from "./register-snug-form"; +import { ApplicationProptype } from "prop-types/application-type"; + +// 해더에서 초대 수신을 동적으로 확인하기 위해 socket 역시 필요하다. +export const RegisterSnug: React.FC = (props) => { + const { Application } = props; -export const RegisterSnug: React.FC = () => { return ( - - + + ); }; diff --git a/client/src/presentation/pages/register-snug/modal.tsx b/client/src/presentation/pages/register-snug/modal.tsx new file mode 100644 index 00000000..af73955e --- /dev/null +++ b/client/src/presentation/pages/register-snug/modal.tsx @@ -0,0 +1,48 @@ +import React from "react"; +import styled from "styled-components"; +import { CustomButton } from "presentation/components/atomic-reusable/custom-button"; + +const Wrapper = styled.section` + position: absolute; + z-index: 1; + background-color: grey; + opacity: 0.9; + color: white; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-around; + width: 20%; + height: 15%; + top: 50%; + border-radius: 10px; + transform: translateY(-50%); +`; + +const content = styled.main` + margin-bottom: 10px; +`; + +interface PropTypes { + onClick?(parameter: any | void): any | void; + message?: string; +} + +export const Modal: React.FC = ({ onClick, message }) => { + return ( + +
{message}
+ +
+ ); +}; \ No newline at end of file diff --git a/client/src/presentation/pages/register-snug/register-snug-form.tsx b/client/src/presentation/pages/register-snug/register-snug-form.tsx index 2baa3394..9ff7211c 100644 --- a/client/src/presentation/pages/register-snug/register-snug-form.tsx +++ b/client/src/presentation/pages/register-snug/register-snug-form.tsx @@ -1,9 +1,12 @@ -import React from "react"; +import React , {useState}from "react"; import styled, { css } from "styled-components"; import { CustomLoginInput } from "presentation/components/atomic-reusable/custom-login-input"; import { CustomButton } from "presentation/components/atomic-reusable/custom-button"; +import { ApplicationProptype } from "prop-types/application-type"; +import { Modal } from "./modal"; +import { User } from "core/entity/user"; -const Wrapper = styled.form` +const Wrapper = styled.section` background-color: #ffffff; height: 100%; width: 100%; @@ -24,7 +27,7 @@ const SnugDescription = styled.span` font-size: 2rem; `; -const InputWrapper = styled.section` +const FormWrapper = styled.form` height: 40%; width: 30%; display: flex; @@ -66,13 +69,64 @@ const ButtonWrapper = styled.section` align-items: center; `; -export const RegisterSnugForm: React.FC = () => { +enum ModalMessage { + "nullCheck" = "입력값을 확인해주세요.", + "failMessage" = "스너그 생성에 실패했습니다." +} + +export const RegisterSnugForm: React.FC = (props) => { + const { Application } = props; + + const [name, setName] = useState(""); + const [description, setDescription] = useState(""); + + const [onModal, setOnModal] = useState(false); + const [modalMessage, setModalMessage] = useState(""); + + const nameHandle = (event: React.ChangeEvent): void => { + setName(event.target.value); + } + + const descriptionHandle = (event: React.ChangeEvent): void => { + setDescription(event.target.value) + } + + const closeModal = () => { + setOnModal(false); + } + + async function onSubmit(event: React.FormEvent) { + event.preventDefault(); + + // local storage에 저장된 데이터를 이용 + const user: User = Application.services.authService.getUserInfo(); + + // input의 널 값 체크 + if(name.length == 0 || description.length == 0) { + setModalMessage(ModalMessage.nullCheck); + setOnModal(true); + return; + } + + const result = await Application.services.snugService.createSnug(name, description, ""); + + // snug 생성 메세지 출력 + if(typeof result === "boolean") { + setModalMessage(ModalMessage.failMessage); + return setOnModal(true); + } + + // 유저 초대 + window.location.href = `/invite-users/${result.id}`; + } + return ( 오직 '우리'를 위한 Snug 만들기 - + {onModal && } + { color={"bdbdbd"} backgroundColor={"#ffffff"} placeholder={"Snug 이름"} + onChange={nameHandle} > Snug 이름을 지어주세요. @@ -96,6 +151,7 @@ export const RegisterSnugForm: React.FC = () => { color={"bdbdbd"} backgroundColor={"#ffffff"} placeholder={"Snug 설명"} + onChange={descriptionHandle} >
이 공간이 갖는 목표를 적어주세요. @@ -112,7 +168,7 @@ export const RegisterSnugForm: React.FC = () => { height={"auto"} > - + ); }; diff --git a/client/src/presentation/pages/register-user/index.tsx b/client/src/presentation/pages/register-user/index.tsx index e2317243..4ab57e5b 100644 --- a/client/src/presentation/pages/register-user/index.tsx +++ b/client/src/presentation/pages/register-user/index.tsx @@ -1,11 +1,13 @@ import React from "react"; import { PageLayout } from "presentation/components/atomic-reusable/page-layout"; import { RegisterUserForm } from "presentation/pages/register-user/register-user-form"; +import { AppChannelMatchProps } from "prop-types/match-extends-types"; -export const RegisterUser: React.FC = () => { +export const RegisterUser: React.FC = props => { + const { Application } = props; return ( - - + + ); }; diff --git a/client/src/presentation/pages/register-user/register-user-form.tsx b/client/src/presentation/pages/register-user/register-user-form.tsx index c8ac9763..7a002c3b 100644 --- a/client/src/presentation/pages/register-user/register-user-form.tsx +++ b/client/src/presentation/pages/register-user/register-user-form.tsx @@ -1,9 +1,18 @@ -import React, { useState } from "react"; +import React, { useState, useCallback } from "react"; import styled from "styled-components"; -import { CustomLoginInput } from "presentation/components/atomic-reusable/custom-login-input"; +import { + validateEmail, + validatePasswordLength +} from "presentation/validation/validation"; +import { ApplicationProptype } from "prop-types/application-type"; import { CustomButton } from "presentation/components/atomic-reusable/custom-button"; +import { EmailInput } from "presentation/components/register-user/inputs/email-input"; +import { NameInput } from "presentation/components/register-user/inputs/name-input"; +import { PasswordInput } from "presentation/components/register-user/inputs/password-input"; +import { PasswordCheckInput } from "presentation/components/register-user/inputs/password-check-input"; +import { Modal } from "presentation/components/register-user/modal"; -const Wrapper = styled.form` +const Wrapper = styled.section` background-color: #ffffff; height: 100%; width: 100%; @@ -24,59 +33,154 @@ const SnugDescription = styled.span` font-size: 2rem; `; -const InputWrapper = styled.section` - height: 40%; +const InputWrapper = styled.form` + height: 50%; width: 30%; display: flex; flex-direction: column; justify-content: space-between; `; -const Input = styled.section``; - const ButtonWrapper = styled.section` display: flex; justify-content: flex-end; `; -export const RegisterUserForm: React.FC = () => { +enum ModalMessage { + "REGISTER_FAILED" = "회원 가입이 실패했습니다.", + "EMAIL_EXISTED" = "이미 있는 이메일입니다.", + "EMAIL_EMPTY" = "이메일을 입력하세요.", + "NOT_ELEGIBLE_FORM" = "제한 조건을 확인해주세요", + "ELEGIBLE_FORM" = "사용 가능한 이메일입니다." +} + +export const RegisterUserForm: React.FC = ({ + Application +}) => { + const [email, setEmail] = useState(""); + const [name, setName] = useState(""); + const [password, setPassword] = useState(""); + const [passwordCheck, setPasswordCheck] = useState(""); + + const [isEmailFormId, setIsEmailFormId] = useState(false); + const [isNotDuplicatedId, setIsNotDuplicatedId] = useState(false); + const [isValidPassword, setIsValidPassword] = useState(false); + const [isPasswordSame, setIsPasswordSame] = useState(false); + + const [modalOn, setModalOn] = useState(false); + const [modalMessage, setModalMessage] = useState(""); + + const closeModal = () => { + setModalOn(false); + }; + + const handleEmailChange = useCallback( + (event: React.ChangeEvent) => { + setEmail(event.target.value); + setIsEmailFormId(validateEmail(event.target.value)); + }, + [email] + ); + + const handleNameChange = useCallback( + (event: React.ChangeEvent) => { + setName(event.target.value); + }, + [name] + ); + + const handlePasswordChange = useCallback( + (event: React.ChangeEvent) => { + setPassword(event.target.value); + setIsValidPassword(validatePasswordLength(event.target.value)); + }, + [password] + ); + + const handlePasswordCheckChange = useCallback( + (event: React.ChangeEvent) => { + setPasswordCheck(event.target.value); + setIsPasswordSame(password === event.target.value); + }, + [passwordCheck] + ); + + const openModalWithMessage = (message: ModalMessage) => { + setModalMessage(message); + setModalOn(true); + }; + + const handleSumbit = async (event: React.FormEvent) => { + event.preventDefault(); + const result = await Application.services.userService.create({ + email, + name, + password + }); + if (!!result) { + window.location.href = "/"; + return; + } + openModalWithMessage(ModalMessage.REGISTER_FAILED); + }; + + const doesEmailExist = async (event: React.MouseEvent) => { + event.preventDefault(); + if (email === "") { + setModalMessage(ModalMessage.EMAIL_EMPTY); + setModalOn(true); + return; + } + const result = await Application.services.userService.doesExist(email); + if (!result) { + setIsNotDuplicatedId(true); + openModalWithMessage(ModalMessage.ELEGIBLE_FORM); + return; + } + setIsNotDuplicatedId(false); + openModalWithMessage(ModalMessage.EMAIL_EXISTED); + }; + return ( 회원 가입을 지금 바로 해보세요! - - - - - - - - - - + {modalOn && } + + 0 && !isEmailFormId} + onClick={doesEmailExist} + disabled={!isEmailFormId} + disabledColor={"rgba(253, 166, 0, 0.5)"} + /> + + 0 && !isValidPassword} + /> + 0 && !isPasswordSame} + /> diff --git a/client/src/presentation/pages/snug/index.tsx b/client/src/presentation/pages/snug/index.tsx index dce14351..7b7a4b7e 100644 --- a/client/src/presentation/pages/snug/index.tsx +++ b/client/src/presentation/pages/snug/index.tsx @@ -1,14 +1,17 @@ -import React from "react"; +import React, { useEffect } from "react"; import styled, { ThemeProvider } from "styled-components"; import { Sidebar } from "./sidebar"; import { SnugHeader } from "./header"; import { ChannelsProvider } from "contexts/channel-context"; import { ModalProvider } from "contexts/modal-context"; import { MessageSection } from "./message-section"; -import { AppSocketChannelMatchProps } from "prop-types/match-extends-types"; +import { AppChannelMatchProps } from "prop-types/match-extends-types"; import { Modals } from "presentation/components/snug/modals"; import { colorTheme } from "presentation/theme/color-theme"; -import { PathParameterContextProvider } from "contexts/path-parameter-context"; +import { + usePathParameterDispatch, + usePathParameter +} from "contexts/path-parameter-context"; const SnugWrapper = styled.section` width: inherit; @@ -20,24 +23,52 @@ const ViewWrapper = styled.section` height: 100%; display: flex; `; -export const Snug: React.FC = props => { - const { Application } = props; +export const Snug: React.FC = props => { + const { Application, match } = props; + const pathParameterDispatch = usePathParameterDispatch(); + const pathParameter = usePathParameter(); + + useEffect(() => { + const id: number = pathParameter.snugId!; + (async function(snigid: number) { + await Application.services.profileService.getProfile( + pathParameter.snugId! + ); + })(id); + }, [pathParameter]); + + useEffect(() => { + if ( + Number(match.params.channelId) == pathParameter.channelId && + Number(match.params.snugId) == pathParameter.snugId + ) + return; + + pathParameterDispatch({ + type: "IN", + channelId: Number(match.params.channelId!) + }); + + pathParameterDispatch({ + type: "GETSNUGID", + snugId: Number(match.params.snugId) + }); + }, []); + return ( - - - - - - - - - - - - - - + + + + + + + + + + + + ); }; diff --git a/client/src/presentation/pages/snug/message-section/content.tsx b/client/src/presentation/pages/snug/message-section/content.tsx index 61fa94de..162e9239 100644 --- a/client/src/presentation/pages/snug/message-section/content.tsx +++ b/client/src/presentation/pages/snug/message-section/content.tsx @@ -1,9 +1,16 @@ -import React from "react"; +import React, { useState, useEffect } from "react"; import styled from "styled-components"; import { ChatContent } from "presentation/components/snug/chat-container"; import { ChatInputBox } from "presentation/components/snug/chat-input-box"; import { MessageContextProvider } from "contexts/messages-context"; -import { AppSocketChannelMatchProps } from "prop-types/match-extends-types"; +import { ProfileSection } from "presentation/pages/snug/profile"; +import { IconBox } from "presentation/components/atomic-reusable/icon-box"; +import LeftArrow from "assets/left-arrow.png"; +import RightArrow from "assets/right-arrow.png"; +import { Preview } from "presentation/components/snug/preview"; +import { AppChannelMatchProps } from "prop-types/match-extends-types"; +import { FileUploadModal } from "presentation/components/snug/file-upload-modal"; +import { usePathParameter } from "contexts/path-parameter-context"; const MessageSectionContentWrapper = styled.section` width: 100%; @@ -13,15 +20,94 @@ const MessageSectionContentWrapper = styled.section` flex-direction: column; overflow: auto; `; +const Wrapper = styled.section` + display: flex; + justify-content: space-between; + height: 100%; + width: 100%; +`; + +const ToggleButton = styled.button` + height: 40px; + width: 40px; + border-bottom-left-radius: 30px; + border-top-left-radius: 30px; + background-color: #ffffff; + color: #000000; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; + text-align: center; + font-weight: 900; + font-size: 1.6rem; + position: fixed; + top: 50%; + right: 0; + transform: translateX(25%); + z-index: 5; +`; + +export const MessageSectionContent: React.FC = props => { + const [toggleProfile, setToggleProfile] = useState(false); -export const MessageSectionContent: React.FC = props => { + const handleClick = () => { + setToggleProfile(!toggleProfile); + }; + + const { Application, history } = props; + const [isParticipated, setIsParticipated] = useState(false); + const pathParameter = usePathParameter(); + // file upload 모달 + // modal state 관리하는 함수 전달 + // file input changed 발생시 modal 활성화 + const [onModal, setModal] = useState(false); + + useEffect(() => { + isInParticipating(); + }, [pathParameter]); + + const isInParticipating = async () => { + try { + const result = await Application.services.channelService.isInParticipating( + pathParameter.channelId! + ); + setIsParticipated(result); + } catch (error) { + console.log(error); + } + }; + + const openModal = () => { + setModal(true); + }; + + const closeModal = () => { + setModal(false); + }; + + // 파일 내용 state return ( - - - - - + + {onModal && } + + + {isParticipated ? ( + + ) : ( + + )} + + + {toggleProfile ? ( + + ) : ( + + )} + + + ); }; diff --git a/client/src/presentation/pages/snug/message-section/index.tsx b/client/src/presentation/pages/snug/message-section/index.tsx index 7f52836b..df6e68db 100644 --- a/client/src/presentation/pages/snug/message-section/index.tsx +++ b/client/src/presentation/pages/snug/message-section/index.tsx @@ -2,7 +2,7 @@ import React from "react"; import styled from "styled-components"; import { MessageSectionHeader } from "./header"; import { MessageSectionContent } from "./content"; -import { AppSocketChannelMatchProps } from "prop-types/match-extends-types"; +import { AppChannelMatchProps } from "prop-types/match-extends-types"; const MessageSectionWrapper = styled.section` height: 100%; @@ -11,7 +11,7 @@ const MessageSectionWrapper = styled.section` flex-direction: column; `; -export const MessageSection: React.FC = props => { +export const MessageSection: React.FC = props => { return ( diff --git a/client/src/presentation/pages/snug/profile/buttons/index.tsx b/client/src/presentation/pages/snug/profile/buttons/index.tsx new file mode 100644 index 00000000..9f39a482 --- /dev/null +++ b/client/src/presentation/pages/snug/profile/buttons/index.tsx @@ -0,0 +1,40 @@ +import React from "react"; +import styled from "styled-components"; +import { CustomButton } from "presentation/components/atomic-reusable/custom-button"; + +const Wrapper = styled.section` + display: flex; + width: 400px; + max-width: 400px; + justify-content: space-around; + align-items: center; + height: 10%; +`; + +interface PropTypes { + toggleModal?(parameter: any | void): any | void; +} + +export const Buttons: React.FC = props => { + const { toggleModal } = props; + + return ( + + + + + ); +}; diff --git a/client/src/presentation/pages/snug/profile/header/index.tsx b/client/src/presentation/pages/snug/profile/header/index.tsx new file mode 100644 index 00000000..ad97d455 --- /dev/null +++ b/client/src/presentation/pages/snug/profile/header/index.tsx @@ -0,0 +1,15 @@ +import React from "react"; +import styled from "styled-components"; + +const Title = styled.header` + height: 10%; + color: ${({ theme }) => theme.snugMainFont}; + text-align: center; + font-size: 2.5rem; + max-width: 400px; + cursor: default; +`; + +export const Header: React.FC = () => { + return Profile; +}; diff --git a/client/src/presentation/pages/snug/profile/index.tsx b/client/src/presentation/pages/snug/profile/index.tsx new file mode 100644 index 00000000..74fbd87b --- /dev/null +++ b/client/src/presentation/pages/snug/profile/index.tsx @@ -0,0 +1,103 @@ +import React, { useState, useEffect, useContext } from "react"; +import styled, { keyframes, css } from "styled-components"; +import { Header } from "./header"; +import { Thumbnail } from "./thumbnail"; +import { Buttons } from "./buttons"; +import { StatusSection } from "./status"; +import { Modal } from "./modal"; +import { Profile } from "core/entity/profile"; +import { globalApplication } from "contexts/application-context"; +import { ChannelRouteComponentType } from "prop-types/channel-match-type"; + +const Wrapper = styled.section` + background-color: ${({ theme }) => theme.snug}; + border: 1px ${({ theme }) => theme.snugBorderColor} solid; + height: auto; + width: 0px; + min-width: 0px; + overflow-y: scroll; + + &::-webkit-scrollbar-thumb { + background: #1d8fc0; + opacity: 0.4; + } + &::-webkit-scrollbar-track { + background-color: grey; + } + transition: 400ms; + ${(props: WrapperPropTypes) => { + if (props.toggleProfile) + return css` + width: 400px; + min-width: 400px; + max-width: 400px; + &::-webkit-scrollbar { + width: 4px; + } + `; + return css` + width: 0px; + &::-webkit-scrollbar { + width: 0px; + } + `; + }}; +`; + +const ImageWrapper = styled.section` + min-width: 400px; + max-width: 400px; + max-height: 40%; +`; +interface WrapperPropTypes { + toggleProfile: boolean; +} +interface PropTypes extends ChannelRouteComponentType { + toggleProfile?: boolean; +} + +export const ProfileSection: React.FC = props => { + const application = useContext(globalApplication); + const [modalDisplay, setModalDisplay] = useState(false); + const [currentProfile, setCurrentProfile] = useState({} as Profile); + const { snugId } = props.match.params; + useEffect(() => { + const requestProfile = async () => { + const profile = await application.services.profileService.getProfile( + parseInt(snugId) + ); + if (!profile) return; + setCurrentProfile(profile); + }; + requestProfile(); + }, []); + + const toggleModal = () => { + setModalDisplay(!modalDisplay); + }; + + const updateProfile = (profile: Profile) => { + setCurrentProfile(profile); + }; + + return ( + + {modalDisplay && ( + + )} +
+ + + + + + + ); +}; diff --git a/client/src/presentation/pages/snug/profile/modal/index.tsx b/client/src/presentation/pages/snug/profile/modal/index.tsx new file mode 100644 index 00000000..94243721 --- /dev/null +++ b/client/src/presentation/pages/snug/profile/modal/index.tsx @@ -0,0 +1,58 @@ +import React from "react"; +import styled from "styled-components"; +import { ModalHeader } from "./modal-header"; +import { ModalBody } from "./modal-body"; +import { Profile } from "core/entity/profile"; + +const BlackBackground = styled.section` + position: fixed; + z-index: 1; + background-color: #ffffff; + width: 100vw; + height: 100vh; + top: 0; + left: 0; + opacity: 0.9; +`; + +const Wrapper = styled.section` + position: fixed; + z-index: 2; + background-color: ${({ theme }) => theme.snugMenuColor}; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-around; + width: 45%; + height: 90%; + top: 50%; + left: 50%; + border-radius: 10px; + transform: translate(-50%, -50%); + padding: 10px; +`; + +interface PropTypes { + toggleModal(): any | void; + updateProfile(profile: Profile): void; + currentProfile: Profile; +} + +export const Modal: React.FC = ({ + toggleModal, + updateProfile, + currentProfile +}) => { + return ( + + + + + + + ); +}; diff --git a/client/src/presentation/pages/snug/profile/modal/modal-body.tsx b/client/src/presentation/pages/snug/profile/modal/modal-body.tsx new file mode 100644 index 00000000..6414a48b --- /dev/null +++ b/client/src/presentation/pages/snug/profile/modal/modal-body.tsx @@ -0,0 +1,117 @@ +import React, { useContext, useState, useEffect } from "react"; +import styled from "styled-components"; +import { ModalLeftBody } from "./modal-left-body"; +import { ModalRightBody } from "./modal-right-body"; +import { globalApplication } from "contexts/application-context"; +import { Profile } from "core/entity/profile"; + +const Wrapper = styled.form` + display: flex; + width: 90%; + height: 70%; + justify-content: space-between; + flex-wrap: wrap; +`; + +const ButtonWrapper = styled.section` + width: 100%; + min-width: 100%; + display: flex; + height: 40px; + justify-content: flex-end; +`; + +const Button = styled.button` + cursor: pointer; + background-color: ${({ theme }) => theme.snugMenuColor}; + color: ${({ theme }) => theme.snugMainFont}; + width: 20%; + border-radius: 5px; + border-color: ${({ theme }) => theme.snugMainFont}; + border: 1px solid; + margin-bottom: 10px; + margin-left: 10px; +`; + +interface PropTypes { + toggleModal(): any | void; + updateProfile(profile: Profile): void; + currentProfile: Profile; +} + +export const ModalBody: React.FC = ({ + toggleModal, + updateProfile, + currentProfile +}) => { + const application = useContext(globalApplication); + + const [description, setDescription] = useState( + currentProfile.description ? currentProfile.description : "" + ); + const [phone, setPhone] = useState( + currentProfile.phone ? currentProfile.phone : "" + ); + const [name, setName] = useState( + currentProfile.name ? currentProfile.name : "" + ); + const [status, setStatus] = useState( + currentProfile.status ? currentProfile.status : "" + ); + + const handleNameChange = (event: React.ChangeEvent) => { + setName(event.target.value); + }; + + const handleStatusChange = (event: React.ChangeEvent) => { + setStatus(event.target.value); + }; + const handleDescriptionChange = ( + event: React.ChangeEvent + ) => { + setDescription(event.target.value); + }; + + const handlePhoneChange = (event: React.ChangeEvent) => { + setPhone(event.target.value); + }; + + const handleSubmit = async (event: React.FormEvent) => { + event.preventDefault(); + const profile = { + ...currentProfile, + name, + description, + status, + phone + } as Profile; + const profilePayload = await application.services.profileService.updateProfile( + profile + ); + if (!profilePayload) return; + updateProfile(profilePayload as Profile); + toggleModal(); + }; + + return ( + + + + + + + + + ); +}; diff --git a/client/src/presentation/pages/snug/profile/modal/modal-header.tsx b/client/src/presentation/pages/snug/profile/modal/modal-header.tsx new file mode 100644 index 00000000..1c5d0b64 --- /dev/null +++ b/client/src/presentation/pages/snug/profile/modal/modal-header.tsx @@ -0,0 +1,31 @@ +import React from "react"; +import styled from "styled-components"; +import LetterXWhite from "assets/letter-x-white.png"; +import { IconBox } from "presentation/components/atomic-reusable/icon-box"; + +const Wrapper = styled.header` + display: flex; + justify-content: space-between; + width: 90%; +`; + +const Title = styled.section` + color: ${({ theme }) => theme.snugMainFont}; + font-weight: bold; + font-size: 2rem; + cursor: default; +`; + +interface PropTypes { + onClick?(): any | void; +} + +export const ModalHeader: React.FC = props => { + const { onClick } = props; + return ( + + Profile 수정 + + + ); +}; diff --git a/client/src/presentation/pages/snug/profile/modal/modal-input.tsx b/client/src/presentation/pages/snug/profile/modal/modal-input.tsx new file mode 100644 index 00000000..22d9b3e3 --- /dev/null +++ b/client/src/presentation/pages/snug/profile/modal/modal-input.tsx @@ -0,0 +1,46 @@ +import React from "react"; +import styled from "styled-components"; + +const Wrapper = styled.section` + height: 100%; + width: 100%; +`; + +const Title = styled.header` + color: ${({ theme }) => theme.snugMainFont}; + margin-bottom: 10px; +`; + +const Input = styled.input` + background-color: #ffffff; + border-color: ${({ theme }) => theme.snugBorderColor}; + border: 1px solid; + appearance: none; + border-radius: 10px; + min-height: 30px; + max-height: 30px; + height: 30px; + width: 100%; + box-sizing: border-box; + padding-left: 4px; + &:active, + :focus { + border: 1px solid #2c5af7; + } +`; + +interface PropTypes { + title: string; + placeholder: string; + onChange?(parameter: any | void): any | void; +} + +export const ModalInput: React.FC = props => { + const { title, onChange, placeholder } = props; + return ( + + {title} + + + ); +}; diff --git a/client/src/presentation/pages/snug/profile/modal/modal-left-body.tsx b/client/src/presentation/pages/snug/profile/modal/modal-left-body.tsx new file mode 100644 index 00000000..b70f52c6 --- /dev/null +++ b/client/src/presentation/pages/snug/profile/modal/modal-left-body.tsx @@ -0,0 +1,60 @@ +import React from "react"; +import styled from "styled-components"; +import { ModalInput } from "./modal-input"; + +const Wrapper = styled.section` + width: 60%; + min-width: 60%; + background-color: ${({ theme }) => theme.snugMenuColor}; + display: flex; + flex-direction: column; +`; + +interface PropTypes { + handleNameChange(parameter: any | void): any | void; + handleDescriptionChange(parameter: any | void): any | void; + handleStatusChange(parameter: any | void): any | void; + handlePhoneChange(parameter: any | void): any | void; + name: string; + description: string; + status: string; + phone: string; +} + +export const ModalLeftBody: React.FC = props => { + const { + handleDescriptionChange, + handleNameChange, + handlePhoneChange, + handleStatusChange, + name, + description, + status, + phone + } = props; + + return ( + + + + + + + ); +}; diff --git a/client/src/presentation/pages/snug/profile/modal/modal-right-body.tsx b/client/src/presentation/pages/snug/profile/modal/modal-right-body.tsx new file mode 100644 index 00000000..f38eb093 --- /dev/null +++ b/client/src/presentation/pages/snug/profile/modal/modal-right-body.tsx @@ -0,0 +1,50 @@ +import React from "react"; +import styled from "styled-components"; +import { ModalThumbnail } from "./thumbnail"; + +const Wrapper = styled.section` + width: 35%; + min-width: 35%; + background-color: color: ${({ theme }) => theme.snugMenuColor}; + display: flex; + flex-direction: column; + justify-content: flex-start; + `; + +const ImageWrapper = styled.section` + height: 30%; + margin-bottom: 10px; +`; + +const Button = styled.button` + cursor: pointer; + background-color: ${({ theme }) => theme.snugMenuColor}; + color: ${({ theme }) => theme.snugMainFont}; + width: 100%; + border-radius: 5px; + border-color: ${({ theme }) => theme.snugMainFont}; + border: 1px solid; + margin-bottom: 10px; +`; + +const Remove = styled.section` + cursor: pointer; + color: #1d8fc0; + font-size: 0.9rem; + text-align: center; + &: hover { + text-decoration: underline; + } +`; + +export const ModalRightBody: React.FC = () => { + return ( + + + + + + Image 삭제하기 + + ); +}; diff --git a/client/src/presentation/pages/snug/profile/modal/thumbnail/index.tsx b/client/src/presentation/pages/snug/profile/modal/thumbnail/index.tsx new file mode 100644 index 00000000..a6b6fe80 --- /dev/null +++ b/client/src/presentation/pages/snug/profile/modal/thumbnail/index.tsx @@ -0,0 +1,11 @@ +import React from "react"; +import styled from "styled-components"; +import Gipyoo from "assets/gipyoo.png"; + +const Image = styled.img` + max-width: 100%; +`; + +export const ModalThumbnail: React.FC = () => { + return ; +}; diff --git a/client/src/presentation/pages/snug/profile/status/index.tsx b/client/src/presentation/pages/snug/profile/status/index.tsx new file mode 100644 index 00000000..8598d708 --- /dev/null +++ b/client/src/presentation/pages/snug/profile/status/index.tsx @@ -0,0 +1,43 @@ +import React from "react"; +import styled from "styled-components"; +import { StatusBarHeader } from "./status-bar-header"; +import { StatusBar } from "./status-bar"; +import { Profile } from "core/entity/profile"; + +const Wrapper = styled.section` + height: auto; + max-width: 400px; + border-bottom: 1px ${({ theme }) => theme.snugBorderColor} solid; +`; + +interface PropTypes { + currentProfile: Profile; + toggleModal(): any | void; +} + +export const StatusSection: React.FC = ({ + currentProfile, + toggleModal +}) => { + const { name, status, role, email } = currentProfile; + return ( + + + + + + + ); +}; diff --git a/client/src/presentation/pages/snug/profile/status/status-bar-header.tsx b/client/src/presentation/pages/snug/profile/status/status-bar-header.tsx new file mode 100644 index 00000000..74ce7123 --- /dev/null +++ b/client/src/presentation/pages/snug/profile/status/status-bar-header.tsx @@ -0,0 +1,44 @@ +import React from "react"; +import styled from "styled-components"; +import { PropTypes } from "./status-bar"; + +const Wrapper = styled.section` + height: 80px; + min-height: 80px; + max-heigth: 80px; + max-width: 400px; + border-bottom: 1px ${({ theme }) => theme.snugBorderColor} solid; + display: flex; + flex-direction: column; + justify-content: center; + padding: 10px; +`; + +const Header = styled.header` + color: ${({ theme }) => theme.snugMainFont}; + font-size: 1.2rem; + font-weight: bold; + margin-bottom: 3px; + &: hover { + text-decoration: underline; + } +`; + +const Contents = styled.main` + color: #3d71a3; + font-size: 0.9rem; + cursor: pointer; + &: hover { + text-decoration: underline; + } +`; + +export const StatusBarHeader: React.FC = props => { + const { header, contents, toggleModal } = props; + return ( + +
{header}
+ {contents} +
+ ); +}; diff --git a/client/src/presentation/pages/snug/profile/status/status-bar.tsx b/client/src/presentation/pages/snug/profile/status/status-bar.tsx new file mode 100644 index 00000000..48f2d9fa --- /dev/null +++ b/client/src/presentation/pages/snug/profile/status/status-bar.tsx @@ -0,0 +1,60 @@ +import React from "react"; +import styled, { css } from "styled-components"; + +const Wrapper = styled.section` + height: 70px; + min-height: 70px; + max-heigth: 70px; + border-bottom: 1px ${({ theme }) => theme.snugBorderColor} solid; + display: flex; + flex-direction: column; + justify-content: center; + padding: 10px; + max-width: 400px; +`; + +const Header = styled.header` + color: ${({ theme }) => theme.snugMainFont}; + font-size: 0.7rem; + margin-bottom: 3px; + &: hover { + text-decoration: underline; + } +`; + +const Contents = styled.main` + color: #3d71a3; + font-size: 0.9rem; + &: hover { + text-decoration: underline; + } + ${(props: PointerTypes) => { + const cursor = props.cursor ? props.cursor : "pointer"; + return css` + cursor: ${cursor}; + `; + }} +`; + +export interface PropTypes { + header: string; + contents: string; + toggleModal?(): any | void; + cursor?: string; +} + +export interface PointerTypes { + cursor?: string; +} + +export const StatusBar: React.FC = props => { + const { header, contents, cursor, toggleModal } = props; + return ( + +
{header}
+ + {contents} + +
+ ); +}; diff --git a/client/src/presentation/pages/snug/profile/thumbnail/index.tsx b/client/src/presentation/pages/snug/profile/thumbnail/index.tsx new file mode 100644 index 00000000..4e3d965d --- /dev/null +++ b/client/src/presentation/pages/snug/profile/thumbnail/index.tsx @@ -0,0 +1,11 @@ +import React from "react"; +import styled from "styled-components"; +import Gipyoo from "assets/gipyoo.png"; + +const Image = styled.img` + max-width: 400px; +`; + +export const Thumbnail: React.FC = () => { + return ; +}; diff --git a/client/src/presentation/pages/snug/sidebar/index.tsx b/client/src/presentation/pages/snug/sidebar/index.tsx index 5c9e6ef5..c4682ad4 100644 --- a/client/src/presentation/pages/snug/sidebar/index.tsx +++ b/client/src/presentation/pages/snug/sidebar/index.tsx @@ -1,7 +1,7 @@ import React from "react"; import styled from "styled-components"; import { ChannelList } from "presentation/components/snug/channel-list"; -import { AppSocketChannelMatchProps } from "prop-types/match-extends-types"; +import { AppChannelMatchProps } from "prop-types/match-extends-types"; const SidebarWrapper = styled.section` color: ${({ theme }) => theme.sidebarFont}; @@ -12,9 +12,8 @@ const SidebarWrapper = styled.section` background-color: ${({ theme }) => theme.sidebar}; `; -export const Sidebar: React.FC = ({ +export const Sidebar: React.FC = ({ match, - socket, history, Application }) => { @@ -22,7 +21,6 @@ export const Sidebar: React.FC = ({ diff --git a/client/src/presentation/theme/color-theme.ts b/client/src/presentation/theme/color-theme.ts index 24e7144a..802cb6da 100644 --- a/client/src/presentation/theme/color-theme.ts +++ b/client/src/presentation/theme/color-theme.ts @@ -6,9 +6,14 @@ export const colorTheme = { sidebarSelect: "#0094ff", sidebarSelectFont: "#000000", snug: "#191d21", + snugHover: "#21272c", snugMainFont: "#ffffff", snugSubFont: "#7f7f7f", snugBorderColor: "#2e363d", snugMenuColor: "#1f2327", - snugSelect: "#0094ff" + snugSelect: "#0094ff", + mainButtonColor: "#27990290", + mainButtonColorHover: "#279902", + subButtonColor: "#cccccc90", + subButtonColorHover: "#cccccc" }; diff --git a/client/src/presentation/validation/validation.ts b/client/src/presentation/validation/validation.ts new file mode 100644 index 00000000..c35b6d41 --- /dev/null +++ b/client/src/presentation/validation/validation.ts @@ -0,0 +1,8 @@ +export const validateEmail = (email: string) => { + const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return re.test(email); +}; + +export const validatePasswordLength = (password: string) => { + return password.length >= 8; +}; diff --git a/client/src/prop-types/channel-match-type.ts b/client/src/prop-types/channel-match-type.ts index a631da25..548184a2 100644 --- a/client/src/prop-types/channel-match-type.ts +++ b/client/src/prop-types/channel-match-type.ts @@ -1,7 +1,8 @@ import { RouteComponentProps } from "react-router"; export interface ChannelMatchType { - channelId: string; + snugId: string; + channelId?: string; } export interface ChannelRouteComponentType diff --git a/client/src/prop-types/invite-match-type.ts b/client/src/prop-types/invite-match-type.ts new file mode 100644 index 00000000..fb1cfea5 --- /dev/null +++ b/client/src/prop-types/invite-match-type.ts @@ -0,0 +1,8 @@ +import { RouteComponentProps } from "react-router"; + +export interface InviteMatchType { + snugId: string; +} + +export interface InviteRouteComponentType + extends RouteComponentProps {} diff --git a/client/src/prop-types/match-extends-types.ts b/client/src/prop-types/match-extends-types.ts index fb63216f..18ed6e65 100644 --- a/client/src/prop-types/match-extends-types.ts +++ b/client/src/prop-types/match-extends-types.ts @@ -1,7 +1,11 @@ import { Context } from "./../context.instance"; import { ChannelRouteComponentType } from "./channel-match-type"; +import { InviteRouteComponentType } from "./invite-match-type"; -export interface AppSocketChannelMatchProps extends ChannelRouteComponentType { +export interface AppChannelMatchProps extends ChannelRouteComponentType { + Application: Context; +} + +export interface AppInviteMatchProps extends InviteRouteComponentType { Application: Context; - socket: any; } diff --git a/client/src/util/cookie.ts b/client/src/util/cookie.ts new file mode 100644 index 00000000..cdffb734 --- /dev/null +++ b/client/src/util/cookie.ts @@ -0,0 +1,17 @@ +export function getCookie(cookieName: string) { + const search = cookieName + "="; + const cookie = document.cookie; + if (cookie.length <= 0) return false; + let startIndex = cookie.indexOf(search); + if (startIndex == -1) return false; + startIndex += search.length; + let endIndex = cookie.indexOf(";", startIndex); + if (endIndex == -1) endIndex = cookie.length; + return unescape(cookie.substring(startIndex, endIndex)); +} + +// 참고 출처 : https://caronjuni.tistory.com/entry/documentcookie%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C + +export const hasCookie = (cookieName: string) => { + return document.cookie === cookieName; +}; diff --git a/server/.env.production b/server/.env.production new file mode 100644 index 00000000..c0d01766 --- /dev/null +++ b/server/.env.production @@ -0,0 +1,37 @@ +# 운영 서버 환경 +DB= +DB_TYPE= +DB_PORT= +DB_USER= +DB_PASSWORD= +DB_LOGGER=file, +DB_LOGGING=query, error +CACHE_HOST= +CACHE_PORT= +CACHE_DURATION= +CACHE_PASSWORD= + +BASE_DIR=dist/ + +# Server Domain +HOST= +PORT=80 + +# Client Domain +CLIENT_DOMAIN= + +# EMAIL ADMIN INFO +MAIL_HOST= +MAIL_PORT= +MAIL_SECURE= +MAIL_ADMIN= +MAIL_PASSWORD= +MIAL_SENDER= +MAIL_POOL= +MAIL_POOL_SIZE= + +# Encryption +PASSWORD_SALT= + +# Dncryption +SECRET_KEY= \ No newline at end of file diff --git a/server/.env.template b/server/.env.template deleted file mode 100644 index b140aea0..00000000 --- a/server/.env.template +++ /dev/null @@ -1,26 +0,0 @@ -# 로컬 개발 환경 -LOCAL_DB= // database 명 -LOCAL_DB_HOST= -LOCAL_DB_PORT= -LOCAL_DB_USER= -LOCAL_DB_PASSWORD= - -# 개발 서버 환경 -DEV_DB= -DEV_DB_HOST= -DEV_DB_PORT= -DEV_DB_USER= -DEV_DB_PASSWORD= - -# 운영 서버 환경 -PROD_DB= -PROD_DB_HOST= -PROD_DB_PORT= -PROD_DB_USER= -PROD_DB_PASSWORD= - -# 현재 배포 환경 설정 -PROFILE= // local: 개발환경, development: 개발 서버, production: 운영 서버 - -# Set up Deploy Port -PORT= // default: 3000 \ No newline at end of file diff --git a/server/.eslintrc b/server/.eslintrc index 275b16f7..09811570 100644 --- a/server/.eslintrc +++ b/server/.eslintrc @@ -15,6 +15,13 @@ "quotes": [ "error", "double" + ], + "@typescript-eslint/no-use-before-define": [ + "error", + { + "functions": false, + "classes": false + } ] } } \ No newline at end of file diff --git a/server/.gitignore b/server/.gitignore index 1d5ab7dc..cca055ef 100644 --- a/server/.gitignore +++ b/server/.gitignore @@ -81,7 +81,7 @@ typings/ .nuxt # react / gatsby -public/ +# public/ # vuepress build output .vuepress/dist @@ -596,7 +596,7 @@ MigrationBackup/ dist ## env -.env +.env.local ## typeorm .idea/ diff --git a/server/ormconfig.js b/server/ormconfig.js index 00142e36..2ecd9418 100644 --- a/server/ormconfig.js +++ b/server/ormconfig.js @@ -1,89 +1,57 @@ -/** - * - * 환경 따라 TypeORM 설정을 다르게 한다. - * - **/ -const profiles = { - local: { - host: process.env.LOCAL_DB_HOST, - port: process.env.LOCAL_DB_PORT, - database: process.env.LOCAL_DB, - username: process.env.LOCAL_DB_USER, - password: process.env.LOCAL_DB_PASSWORD, - synchronize: true, - logger: "advanced-console", - logging: ["query", "warn", "error"], - }, - development: { - host: process.env.DEV_DB_HOST, - port: process.env.DEV_DB_PORT, - database: process.env.DEV_DB, - username: process.env.DEV_DB_USER, - password: process.env.DEV_DB_PASSWORD, - synchronize: false, - logger: "file", - logging: "all", - }, - production: { - host: process.env.PROD_DB_HOST, - port: process.env.PROD_DB_PORT, - database: process.env.PROD_DB, - username: process.env.PROD_DB_USER, - password: process.env.PROD_DB_PASSWORD, - synchronize: false, - logger: "file", - logging: ["query", "error"], +const path = require("path"); +require("dotenv").config({ path: path.join(".env." + process.env.NODE_ENV) }); + +const dbOptions = { + type: process.env.DB_TYPE, + host: process.env.DB_HOST, + port: process.env.DB_PORT, + database: process.env.DB, + username: process.env.DB_USER, + password: process.env.DB_PASSWORD, + synchronize: true, + logger: process.env.DB_LOGGER, + logging: process.env.DB_LOGGING.split(","), + cache: { + type: "redis", + duration: process.env.CACHE_DURATION, // milliseconds + options: { + host: process.env.CACHE_HOST, + port: process.env.CACHE_PORT, + password: process.env.CACHE_PASSWORD } + }, + extra: { + connectionLimit: 10, + queueLimit: 5 + }, + maxQueryExecutionTime: 1000, // milliseconds + migrationsRun: false, + dropSchema: false }; -/** - * - * TypeORM 공통 설정을 다르게 한다. - * - **/ -const common = { - type: "mysql", - dropSchema: false, - maxQueryExecutionTime: 1000, // milliseconds - entities: [ - process.env.BASE_DIR + "entity/**/*.{ts,js}" - ], - migrations: [ - process.env.BASE_DIR + "migration/**/*.{ts,js}" - ], - subscribers: [ - process.env.BASE_DIR + "subscriber/**/*.{ts,js}" - ], - migrationsRun: false, - cli: { - entitiesDir: "src/entity", - migrationsDir: "src/migration", - subscribersDir: "src/subscriber" - }, - extra: { - connectionLimit: 10, - queueLimit: 5 - } +const cliOptions = { + entities: [process.env.BASE_DIR + "domain/**/*.{ts,js}"], + migrations: [process.env.BASE_DIR + "migration/**/*.{ts,js}"], + subscribers: [process.env.BASE_DIR + "subscriber/**/*.{ts,js}"], + cli: { + entitiesDir: "src/domain", + migrationsDir: "src/migration", + subscribersDir: "src/subscriber" + } }; -/** - * - * PROFILE 환경 변수에 따라, TypeORM 설정 정보를 다르게 제공한다. - * default 는 "local" 이다. - * - **/ const setUpDbOptions = () => { - let profile = process.env.NODE_ENV; - if (!Object.keys(profiles).includes(profile)) { - profile = "local"; - - } - - return { - ...profiles[profile], - ...common - }; + const profile = process.env.NODE_ENV; + if (profile !== "local" && profile !== "production") { + new Error( + "NODE_ENV 환경변수를 설정해 주세요 :: ex) 'local' or'production'" + ); + } + return { + ...dbOptions, + ...cliOptions + }; }; -module.exports = setUpDbOptions(); \ No newline at end of file +module.exports = setUpDbOptions(); diff --git a/server/package-lock.json b/server/package-lock.json index a61f03ca..2c02617b 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -14,18 +14,18 @@ } }, "@babel/core": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.2.tgz", - "integrity": "sha512-eeD7VEZKfhK1KUXGiyPFettgF3m513f8FoBSWiQ1xTvl1RAopLs42Wp9+Ze911I6H0N9lNqJMDgoZT7gHsipeQ==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.4.tgz", + "integrity": "sha512-+bYbx56j4nYBmpsWtnPUsKW3NdnYxbqyfrP2w9wILBuHzdfIKz9prieZK0DFPyIzkjYVUe4QkusGL07r5pXznQ==", "dev": true, "requires": { "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.7.2", - "@babel/helpers": "^7.7.0", - "@babel/parser": "^7.7.2", - "@babel/template": "^7.7.0", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.7.2", + "@babel/generator": "^7.7.4", + "@babel/helpers": "^7.7.4", + "@babel/parser": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@babel/types": "^7.7.4", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "json5": "^2.1.0", @@ -33,38 +33,69 @@ "resolve": "^1.3.2", "semver": "^5.4.1", "source-map": "^0.5.0" + }, + "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 + }, + "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/generator": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.2.tgz", - "integrity": "sha512-WthSArvAjYLz4TcbKOi88me+KmDJdKSlfwwN8CnUYn9jBkzhq0ZEPuBfkAWIvjJ3AdEV1Cf/+eSQTnp3IDJKlQ==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.4.tgz", + "integrity": "sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg==", "dev": true, "requires": { - "@babel/types": "^7.7.2", + "@babel/types": "^7.7.4", "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.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.0.tgz", - "integrity": "sha512-tDsJgMUAP00Ugv8O2aGEua5I2apkaQO7lBGUq1ocwN3G23JE5Dcq0uh3GvFTChPa4b40AWiAsLvCZOA2rdnQ7Q==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz", + "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.7.0", - "@babel/template": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/helper-get-function-arity": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/types": "^7.7.4" } }, "@babel/helper-get-function-arity": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.0.tgz", - "integrity": "sha512-tLdojOTz4vWcEnHWHCuPN5P85JLZWbm5Fx5ZsMEMPhF3Uoe3O7awrbM2nQ04bDOUToH/2tH/ezKEOR8zEYzqyw==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz", + "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==", "dev": true, "requires": { - "@babel/types": "^7.7.0" + "@babel/types": "^7.7.4" } }, "@babel/helper-plugin-utils": { @@ -74,23 +105,23 @@ "dev": true }, "@babel/helper-split-export-declaration": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.0.tgz", - "integrity": "sha512-HgYSI8rH08neWlAH3CcdkFg9qX9YsZysZI5GD8LjhQib/mM0jGOZOVkoUiiV2Hu978fRtjtsGsW6w0pKHUWtqA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz", + "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==", "dev": true, "requires": { - "@babel/types": "^7.7.0" + "@babel/types": "^7.7.4" } }, "@babel/helpers": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.7.0.tgz", - "integrity": "sha512-VnNwL4YOhbejHb7x/b5F39Zdg5vIQpUUNzJwx0ww1EcVRt41bbGRZWhAURrfY32T5zTT3qwNOQFWpn+P0i0a2g==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.7.4.tgz", + "integrity": "sha512-ak5NGZGJ6LV85Q1Zc9gn2n+ayXOizryhjSUBTdu5ih1tlVCJeuQENzc4ItyCVhINVXvIT/ZQ4mheGIsfBkpskg==", "dev": true, "requires": { - "@babel/template": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/template": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@babel/types": "^7.7.4" } }, "@babel/highlight": { @@ -105,52 +136,75 @@ } }, "@babel/parser": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.3.tgz", - "integrity": "sha512-bqv+iCo9i+uLVbI0ILzKkvMorqxouI+GbV13ivcARXn9NNEabi2IEz912IgNpT/60BNXac5dgcfjb94NjsF33A==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.4.tgz", + "integrity": "sha512-jIwvLO0zCL+O/LmEJQjWA75MQTWwx3c3u2JOTDK5D3/9egrWRRA0/0hk9XXywYnXZVVpzrBYeIQTmhwUaePI9g==", "dev": true }, "@babel/plugin-syntax-object-rest-spread": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", - "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.7.4.tgz", + "integrity": "sha512-mObR+r+KZq0XhRVS2BrBKBpr5jqrqzlPvS9C9vuOf5ilSwzloAl7RPWLrgKdWS6IreaVrjHxTjtyqFiOisaCwg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" } }, "@babel/template": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.0.tgz", - "integrity": "sha512-OKcwSYOW1mhWbnTBgQY5lvg1Fxg+VyfQGjcBduZFljfc044J5iDlnDSfhQ867O17XHiSCxYHUxHg2b7ryitbUQ==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz", + "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4" } }, "@babel/traverse": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.2.tgz", - "integrity": "sha512-TM01cXib2+rgIZrGJOLaHV/iZUAxf4A0dt5auY6KNZ+cm6aschuJGqKJM3ROTt3raPUdIDk9siAufIFEleRwtw==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz", + "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==", "dev": true, "requires": { "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.7.2", - "@babel/helper-function-name": "^7.7.0", - "@babel/helper-split-export-declaration": "^7.7.0", - "@babel/parser": "^7.7.2", - "@babel/types": "^7.7.2", + "@babel/generator": "^7.7.4", + "@babel/helper-function-name": "^7.7.4", + "@babel/helper-split-export-declaration": "^7.7.4", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4", "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" + } + }, + "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 + }, + "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.7.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.2.tgz", - "integrity": "sha512-YTf6PXoh3+eZgRCBzzP25Bugd2ngmpQVrk7kXX0i5N9BO7TFBtIgZYs7WtxtOGs8e6A4ZI7ECkbBCEHeXocvOA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", "dev": true, "requires": { "esutils": "^2.0.2", @@ -221,6 +275,29 @@ "rimraf": "^2.5.4", "slash": "^2.0.0", "strip-ansi": "^5.0.0" + }, + "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": "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" + } + } } }, "@jest/environment": { @@ -273,14 +350,6 @@ "slash": "^2.0.0", "source-map": "^0.6.0", "string-length": "^2.0.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } } }, "@jest/source-map": { @@ -292,14 +361,6 @@ "callsites": "^3.0.0", "graceful-fs": "^4.1.15", "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } } }, "@jest/test-result": { @@ -347,14 +408,6 @@ "slash": "^2.0.0", "source-map": "^0.6.1", "write-file-atomic": "2.4.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } } }, "@jest/types": { @@ -368,6 +421,217 @@ "@types/yargs": "^13.0.0" } }, + "@opencensus/core": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@opencensus/core/-/core-0.0.9.tgz", + "integrity": "sha512-31Q4VWtbzXpVUd2m9JS6HEaPjlKvNMOiF7lWKNmXF84yUcgfAFL5re7/hjDmdyQbOp32oGc+RFV78jXIldVz6Q==", + "requires": { + "continuation-local-storage": "^3.2.1", + "log-driver": "^1.2.7", + "semver": "^5.5.0", + "shimmer": "^1.2.0", + "uuid": "^3.2.1" + } + }, + "@opencensus/propagation-b3": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@opencensus/propagation-b3/-/propagation-b3-0.0.8.tgz", + "integrity": "sha512-PffXX2AL8Sh0VHQ52jJC4u3T0H6wDK6N/4bg7xh4ngMYOIi13aR1kzVvX1sVDBgfGwDOkMbl4c54Xm3tlPx/+A==", + "requires": { + "@opencensus/core": "^0.0.8", + "uuid": "^3.2.1" + }, + "dependencies": { + "@opencensus/core": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@opencensus/core/-/core-0.0.8.tgz", + "integrity": "sha512-yUFT59SFhGMYQgX0PhoTR0LBff2BEhPrD9io1jWfF/VDbakRfs6Pq60rjv0Z7iaTav5gQlttJCX2+VPxFWCuoQ==", + "requires": { + "continuation-local-storage": "^3.2.1", + "log-driver": "^1.2.7", + "semver": "^5.5.0", + "shimmer": "^1.2.0", + "uuid": "^3.2.1" + } + } + } + }, + "@pm2/agent": { + "version": "0.5.26", + "resolved": "https://registry.npmjs.org/@pm2/agent/-/agent-0.5.26.tgz", + "integrity": "sha512-pqiS87IiUprkSR7SG0RKMATuYXl4QjH1tSSUwM4wJcovRT4pD5dvnnu61w9y/4/Ur5V/+a7bqS8bZz51y3U2iA==", + "requires": { + "async": "^2.6.0", + "chalk": "^2.3.2", + "eventemitter2": "^5.0.1", + "fclone": "^1.0.11", + "moment": "^2.21.0", + "nssocket": "^0.6.0", + "pm2-axon": "^3.2.0", + "pm2-axon-rpc": "^0.5.0", + "proxy-agent": "^3.1.0", + "semver": "^5.5.0", + "ws": "^5.1.0" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "requires": { + "lodash": "^4.17.14" + } + }, + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "requires": { + "async-limiter": "~1.0.0" + } + } + } + }, + "@pm2/agent-node": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@pm2/agent-node/-/agent-node-1.1.10.tgz", + "integrity": "sha512-xRcrk7OEwhS3d/227/kKGvxgmbIi6Yyp27FzGlFNermEKhgddmFaRnmd7GRLIsBM/KB28NrwflBZulzk/mma6g==", + "requires": { + "debug": "^3.1.0", + "eventemitter2": "^5.0.1", + "proxy-agent": "^3.0.3", + "ws": "^6.0.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "requires": { + "async-limiter": "~1.0.0" + } + } + } + }, + "@pm2/io": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@pm2/io/-/io-4.3.3.tgz", + "integrity": "sha512-ENGsdSVpnwbYMGdeB0/Xy2eZYo7oltzApoCsMD4ssqWNXDg9C4uQZy5J09iPsb0IHFwSDjU5oylXdwKDSoqODw==", + "requires": { + "@opencensus/core": "^0.0.9", + "@opencensus/propagation-b3": "^0.0.8", + "@pm2/agent-node": "^1.1.10", + "async": "~2.6.1", + "debug": "3.1.0", + "eventemitter2": "~5.0.1", + "require-in-the-middle": "^5.0.0", + "semver": "5.5.0", + "shimmer": "~1.2.0", + "signal-exit": "3.0.2", + "tslib": "1.9.3" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "requires": { + "lodash": "^4.17.14" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + } + } + }, + "@pm2/js-api": { + "version": "0.5.60", + "resolved": "https://registry.npmjs.org/@pm2/js-api/-/js-api-0.5.60.tgz", + "integrity": "sha512-CvAbpIB7ObOuwvqhDBB/E4Z4ANRx2dBk08zYpGPNg+1fDj14FJg2e7DWA8bblSGNC8QarIXPaqPDJBL1e8cRQw==", + "requires": { + "async": "^2.4.1", + "axios": "^0.19.0", + "debug": "^2.6.8", + "eventemitter2": "^4.1.0", + "ws": "^3.0.0" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "requires": { + "lodash": "^4.17.14" + } + }, + "eventemitter2": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-4.1.2.tgz", + "integrity": "sha1-DhqEd6+CGm7zmVsxG/dMI6UkfxU=" + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + } + } + }, + "@pm2/pm2-version-check": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@pm2/pm2-version-check/-/pm2-version-check-1.0.3.tgz", + "integrity": "sha512-SBuYsh+o35knItbRW97vl5/5nEc5c5DYP7PxjyPLOfmm9bMaDsVeATXjXMBy6+KLlyrYWHZxGbfXe003NnHClg==", + "requires": { + "debug": "^4.1.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "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==" + } + } + }, "@sinonjs/commons": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.6.0.tgz", @@ -437,14 +701,20 @@ } }, "@types/babel__traverse": { - "version": "7.0.7", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.7.tgz", - "integrity": "sha512-CeBpmX1J8kWLcDEnI3Cl2Eo6RfbGvzUctA+CjZUhOKDFbLfcr7fc4usEqLNWetrlJd7RhAkyYe2czXop4fICpw==", + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.8.tgz", + "integrity": "sha512-yGeB2dHEdvxjP0y4UbRtQaSkXJ9649fYCmIdRoul5kfAoGCwxuCbMhag0k3RPfnuh9kPGm8x89btcfDEXdVWGw==", "dev": true, "requires": { "@babel/types": "^7.3.0" } }, + "@types/bcryptjs": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.2.tgz", + "integrity": "sha512-LiMQ6EOPob/4yUL66SZzu6Yh77cbzJFYll+ZfaPiPPFswtIlA/Fs1MzdKYA7JApHU49zQTbJGX3PDmCpIdDBRQ==", + "dev": true + }, "@types/body-parser": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.1.tgz", @@ -484,15 +754,6 @@ "integrity": "sha512-aRnpPa7ysx3aNW60hTiCtLHlQaIFsXFCgQlpakNgDNVFzbtusSY8PwjAQgRWfSk0ekNoBjO51eQRB6upA9uuyw==", "dev": true }, - "@types/errorhandler": { - "version": "0.0.32", - "resolved": "https://registry.npmjs.org/@types/errorhandler/-/errorhandler-0.0.32.tgz", - "integrity": "sha512-wC9CfwPMIzklPd5lEYC8HnQdlMC1PswlohWmEDMWlw+E/rMYuz5eSqKBc72Earb29KptKJrRl77qVRJzrZndww==", - "dev": true, - "requires": { - "@types/express": "*" - } - }, "@types/eslint": { "version": "6.1.3", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-6.1.3.tgz", @@ -510,9 +771,9 @@ "dev": true }, "@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "version": "0.0.40", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.40.tgz", + "integrity": "sha512-p3KZgMto/JyxosKGmnLDJ/dG5wf+qTRMUjHJcspC2oQKa4jP7mz+tv0ND56lLBu3ojHlhzY33Ol+khLyNmilkA==", "dev": true }, "@types/express": { @@ -527,9 +788,9 @@ } }, "@types/express-serve-static-core": { - "version": "4.16.11", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.16.11.tgz", - "integrity": "sha512-K8d2M5t3tBQimkyaYTXxtHYyoJPUEhy2/omVRnTAKw5FEdT+Ft6lTaTOpoJdHeG+mIwQXXtqiTcYZ6IR8LTzjQ==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.0.tgz", + "integrity": "sha512-Xnub7w57uvcBqFdIGoRg1KhNOeEj0vB6ykUM7uFWyxvbdE89GFyqgmUcanAriMr4YOxNFZBAWkfcWIb4WBPt3g==", "dev": true, "requires": { "@types/node": "*", @@ -562,20 +823,14 @@ } }, "@types/jest": { - "version": "24.0.22", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.22.tgz", - "integrity": "sha512-t2OvhNZnrNjlzi2i0/cxbLVM59WN15I2r1Qtb7wDv28PnV9IzrPtagFRey/S9ezdLD0zyh1XGMQIEQND2YEfrw==", + "version": "24.0.23", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.23.tgz", + "integrity": "sha512-L7MBvwfNpe7yVPTXLn32df/EK+AMBFAFvZrRuArGs7npEWnlziUXK+5GMIUTI4NIuwok3XibsjXCs5HxviYXjg==", "dev": true, "requires": { - "@types/jest-diff": "*" + "jest-diff": "^24.3.0" } }, - "@types/jest-diff": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/@types/jest-diff/-/jest-diff-20.0.1.tgz", - "integrity": "sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA==", - "dev": true - }, "@types/json-schema": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.3.tgz", @@ -588,6 +843,21 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "@types/jsonwebtoken": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.3.5.tgz", + "integrity": "sha512-VGM1gb+LwsQ5EPevvbvdnKncajBdYqNcrvixBif1BsiDQiSF1q+j4bBTvKC6Bt9n2kqNSx+yNTY2TVJ360E7EQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/lodash": { + "version": "4.14.149", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz", + "integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==", + "dev": true + }, "@types/mime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz", @@ -614,9 +884,19 @@ } }, "@types/node": { - "version": "8.10.59", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.59.tgz", - "integrity": "sha512-8RkBivJrDCyPpBXhVZcjh7cQxVBSmRk9QM7hOketZzp6Tg79c0N8kkpAIito9bnJ3HCVCHVYz+KHTEbfQNfeVQ==" + "version": "12.12.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.14.tgz", + "integrity": "sha512-u/SJDyXwuihpwjXy7hOOghagLEV1KdAST6syfnOk6QZAMzZuWZqXy5aYYZbh8Jdpd4escVFP0MvftHNDb9pruA==", + "dev": true + }, + "@types/nodemailer": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.2.2.tgz", + "integrity": "sha512-vDbSSe3+bBXYgibKs8duOrH7bhAv1hMHl3Vtdr3KmXZWLfi5WtIg3X6D/+K4SMK1RbNlm5QZBQCOldST/sVjjg==", + "dev": true, + "requires": { + "@types/node": "*" + } }, "@types/range-parser": { "version": "1.2.3", @@ -644,6 +924,7 @@ "version": "2.1.4", "resolved": "https://registry.npmjs.org/@types/socket.io/-/socket.io-2.1.4.tgz", "integrity": "sha512-cI98INy7tYnweTsUlp8ocveVdAxENUThO0JsLSCs51cjOP2yV5Mqo5QszMDPckyRRA+PO6+wBgKvGvHUCc23TQ==", + "dev": true, "requires": { "@types/node": "*" } @@ -673,6 +954,15 @@ "@types/superagent": "*" } }, + "@types/winston": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/winston/-/winston-2.4.4.tgz", + "integrity": "sha512-BVGCztsypW8EYwJ+Hq+QNYiT/MUyCif0ouBH+flrY66O5W+KIXAMML6E/0fJpm7VjIzgangahl5S03bJJQGrZw==", + "dev": true, + "requires": { + "winston": "*" + } + }, "@types/yargs": { "version": "13.0.3", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.3.tgz", @@ -689,55 +979,71 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.7.0.tgz", - "integrity": "sha512-H5G7yi0b0FgmqaEUpzyBlVh0d9lq4cWG2ap0RKa6BkF3rpBb6IrAoubt1NWh9R2kRs/f0k6XwRDiDz3X/FqXhQ==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.10.0.tgz", + "integrity": "sha512-rT51fNLW0u3fnDGnAHVC5nu+Das+y2CpW10yqvf6/j5xbuUV3FxA3mBaIbM24CXODXjbgUznNb4Kg9XZOUxKAw==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "2.7.0", - "eslint-utils": "^1.4.2", + "@typescript-eslint/experimental-utils": "2.10.0", + "eslint-utils": "^1.4.3", "functional-red-black-tree": "^1.0.1", - "regexpp": "^2.0.1", + "regexpp": "^3.0.0", "tsutils": "^3.17.1" } }, "@typescript-eslint/experimental-utils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.7.0.tgz", - "integrity": "sha512-9/L/OJh2a5G2ltgBWJpHRfGnt61AgDeH6rsdg59BH0naQseSwR7abwHq3D5/op0KYD/zFT4LS5gGvWcMmegTEg==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.10.0.tgz", + "integrity": "sha512-FZhWq6hWWZBP76aZ7bkrfzTMP31CCefVIImrwP3giPLcoXocmLTmr92NLZxuIcTL4GTEOE33jQMWy9PwelL+yQ==", "dev": true, "requires": { "@types/json-schema": "^7.0.3", - "@typescript-eslint/typescript-estree": "2.7.0", + "@typescript-eslint/typescript-estree": "2.10.0", "eslint-scope": "^5.0.0" } }, "@typescript-eslint/parser": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.7.0.tgz", - "integrity": "sha512-ctC0g0ZvYclxMh/xI+tyqP0EC2fAo6KicN9Wm2EIao+8OppLfxji7KAGJosQHSGBj3TcqUrA96AjgXuKa5ob2g==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.10.0.tgz", + "integrity": "sha512-wQNiBokcP5ZsTuB+i4BlmVWq6o+oAhd8en2eSm/EE9m7BgZUIfEeYFd6z3S+T7bgNuloeiHA1/cevvbBDLr98g==", "dev": true, "requires": { "@types/eslint-visitor-keys": "^1.0.0", - "@typescript-eslint/experimental-utils": "2.7.0", - "@typescript-eslint/typescript-estree": "2.7.0", + "@typescript-eslint/experimental-utils": "2.10.0", + "@typescript-eslint/typescript-estree": "2.10.0", "eslint-visitor-keys": "^1.1.0" } }, "@typescript-eslint/typescript-estree": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.7.0.tgz", - "integrity": "sha512-vVCE/DY72N4RiJ/2f10PTyYekX2OLaltuSIBqeHYI44GQ940VCYioInIb8jKMrK9u855OEJdFC+HmWAZTnC+Ag==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.10.0.tgz", + "integrity": "sha512-oOYnplddQNm/LGVkqbkAwx4TIBuuZ36cAQq9v3nFIU9FmhemHuVzAesMSXNQDdAzCa5bFgCrfD3JWhYVKlRN2g==", "dev": true, "requires": { "debug": "^4.1.1", - "glob": "^7.1.4", + "eslint-visitor-keys": "^1.1.0", + "glob": "^7.1.6", "is-glob": "^4.0.1", "lodash.unescape": "4.0.1", "semver": "^6.3.0", "tsutils": "^3.17.1" }, "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", @@ -747,18 +1053,11 @@ } }, "abab": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.2.tgz", - "integrity": "sha512-2scffjvioEmNz0OyDSLGWDfKCVwaKc6l9Pm9kOIREU13ClXZvHpg/nRL5xyjSSSLhOnXqft2HpsAzNEEA8cFFg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz", + "integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==", "dev": true }, - "abbrev": { - "version": "1.1.1", - "resolved": false, - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true, - "optional": true - }, "accepts": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", @@ -785,9 +1084,9 @@ }, "dependencies": { "acorn": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz", - "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", + "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==", "dev": true } } @@ -809,6 +1108,14 @@ "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" }, + "agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "requires": { + "es6-promisify": "^5.0.0" + } + }, "ajv": { "version": "6.10.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", @@ -821,16 +1128,37 @@ "uri-js": "^4.2.2" } }, + "amp": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/amp/-/amp-0.3.1.tgz", + "integrity": "sha1-at+NWKdPNh6CwfqNOJwHnhOfxH0=" + }, + "amp-message": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/amp-message/-/amp-message-0.1.2.tgz", + "integrity": "sha1-p48cmJlQh602GSpBKY5NtJ49/EU=", + "requires": { + "amp": "0.3.1" + } + }, + "ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==" + }, "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 + "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": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" }, "ansi-styles": { "version": "3.2.1", @@ -860,29 +1188,10 @@ "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.2.1.tgz", "integrity": "sha512-91IFKeKk7FjfmezPKkwtaRvSpnUc4gDwPAjA1YZ9Gn0q0PPeW+vbeUsZuyDwjI7+QTHhcLen2v25fi/AmhvbJA==" }, - "aproba": { - "version": "1.2.0", - "resolved": false, - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "resolved": false, - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, "arg": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.1.tgz", - "integrity": "sha512-SlmP3fEA88MBv0PypnXZ8ZfJhwmDeIE3SP71j37AiXQBXYosPV0x6uISAaHYSlSVhmHOVkomen0tbGk6Anlebw==", - "dev": true + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.2.tgz", + "integrity": "sha512-+ytCkGcBtHZ3V2r2Z06AncYO8jz46UEamcspGoU8lHcEbpn6J77QK0vdWvChsclg/tM5XIJC5tnjmPp7Eq6Obg==" }, "argparse": { "version": "1.0.10", @@ -959,12 +1268,22 @@ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, + "ast-types": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.2.tgz", + "integrity": "sha512-uWMHxJxtfj/1oZClOxDEV1sQ1HCDkA4MG8Gr69KKeBjEVH0R84WlejZ0y2DcwyBlpAEMltmVYkVgqfLFb2oyiA==" + }, "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": "3.1.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.1.0.tgz", + "integrity": "sha512-4vx/aaY6j/j3Lw3fbCHNWP0pPaTCew3F6F3hYyl/tHs/ndmV1q7NW9T5yuJ2XAGwdQrP+6Wu20x06U4APo/iQQ==" + }, "async-hook-jl": { "version": "1.7.6", "resolved": "https://registry.npmjs.org/async-hook-jl/-/async-hook-jl-1.7.6.tgz", @@ -978,6 +1297,15 @@ "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" }, + "async-listener": { + "version": "0.6.10", + "resolved": "https://registry.npmjs.org/async-listener/-/async-listener-0.6.10.tgz", + "integrity": "sha512-gpuo6xOyF4D5DE5WvyqZdPA3NGhiT6Qf07l7DCB0wwDEsLvDIbCr6j9S5aj5Ch96dLace5tXVzWBZkxU/c5ohw==", + "requires": { + "semver": "^5.3.0", + "shimmer": "^1.1.0" + } + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -997,11 +1325,27 @@ "dev": true }, "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.0.tgz", + "integrity": "sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A==", "dev": true }, + "axios": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.0.tgz", + "integrity": "sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==", + "requires": { + "follow-redirects": "1.5.10", + "is-buffer": "^2.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==" + } + } + }, "babel-jest": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.9.0.tgz", @@ -1027,10 +1371,46 @@ "find-up": "^3.0.0", "istanbul-lib-instrument": "^3.3.0", "test-exclude": "^5.2.3" - } - }, - "babel-plugin-jest-hoist": { - "version": "24.9.0", + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-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" + } + }, + "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 + } + } + }, + "babel-plugin-jest-hoist": { + "version": "24.9.0", "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.9.0.tgz", "integrity": "sha512-2EMA2P8Vp7lG0RAzr4HXqtYwacfMErOuv1U3wrvxHX6rD1sV6xS3WXG3r8TRQ2r6w8OhvSdWt+z41hQNwNm3Xw==", "dev": true, @@ -1110,12 +1490,6 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true } } }, @@ -1151,6 +1525,11 @@ "tweetnacl": "^0.14.3" } }, + "bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" + }, "better-assert": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", @@ -1164,11 +1543,26 @@ "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz", "integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ==" }, + "binary-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", + "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==" + }, + "blessed": { + "version": "0.1.81", + "resolved": "https://registry.npmjs.org/blessed/-/blessed-0.1.81.tgz", + "integrity": "sha1-+WLWh+wsNpVwrnGvhDJW5tDKESk=" + }, "blob": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==" }, + "bodec": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bodec/-/bodec-0.1.0.tgz", + "integrity": "sha1-vIUVVUMPI8n3ZQp172TGqUw0GMw=" + }, "body-parser": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", @@ -1184,38 +1578,6 @@ "qs": "6.7.0", "raw-body": "2.4.0", "type-is": "~1.6.17" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" - } } }, "brace-expansion": { @@ -1306,11 +1668,15 @@ "ieee754": "^1.1.4" } }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" }, "bytes": { "version": "3.1.0", @@ -1381,12 +1747,76 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, - "chownr": { - "version": "1.1.1", - "resolved": false, - "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", - "dev": true, - "optional": true + "charm": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/charm/-/charm-0.1.2.tgz", + "integrity": "sha1-BsIe7RobBq62dVPNxT4jJ0usIpY=" + }, + "chokidar": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", + "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.2.0" + }, + "dependencies": { + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fsevents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", + "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "optional": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + } + } }, "ci-info": { "version": "2.0.0", @@ -1439,11 +1869,6 @@ "yargs": "^15.0.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" - }, "ansi-styles": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.0.tgz", @@ -1462,16 +1887,6 @@ "supports-color": "^7.1.0" } }, - "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1485,74 +1900,11 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, - "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==" - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "requires": { - "p-locate": "^4.1.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==", - "requires": { - "p-limit": "^2.2.0" - } - }, - "parse5": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", - "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" - }, - "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==" - }, - "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==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "requires": { - "ansi-regex": "^5.0.0" - } - }, "supports-color": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", @@ -1561,16 +1913,6 @@ "has-flag": "^4.0.0" } }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, "yargs": { "version": "15.0.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.0.2.tgz", @@ -1588,15 +1930,51 @@ "y18n": "^4.0.0", "yargs-parser": "^16.1.0" } + } + } + }, + "cli-table-redemption": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cli-table-redemption/-/cli-table-redemption-1.0.1.tgz", + "integrity": "sha512-SjVCciRyx01I4azo2K2rcc0NP/wOceXGzG1ZpYkEulbbIxDA/5YWv0oxG2HtQ4v8zPC6bgbRI7SbNaTZCxMNkg==", + "requires": { + "chalk": "^1.1.3" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, - "yargs-parser": { - "version": "16.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-16.1.0.tgz", - "integrity": "sha512-H/V41UNZQPkUMIT5h5hiwg4QKIY1RPvoBV4XcjUbRM8Bk2oKqqyZ0DIEbTFZB0XjbtSPG8SAa/0DxCQmiRgzKg==", + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "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=", + "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=" } } }, @@ -1607,13 +1985,13 @@ "dev": true }, "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" } }, "cls-hooked": { @@ -1629,13 +2007,7 @@ "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "code-point-at": { - "version": "1.1.0", - "resolved": false, - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" }, "collection-visit": { "version": "1.0.0", @@ -1647,6 +2019,15 @@ "object-visit": "^1.0.0" } }, + "color": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", + "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", + "requires": { + "color-convert": "^1.9.1", + "color-string": "^1.5.2" + } + }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -1660,6 +2041,34 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, + "color-string": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", + "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "colornames": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/colornames/-/colornames-1.1.1.tgz", + "integrity": "sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y=" + }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + }, + "colorspace": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz", + "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==", + "requires": { + "color": "3.0.x", + "text-hex": "1.0.x" + } + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -1682,10 +2091,9 @@ "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" }, "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" }, "component-inherit": { "version": "0.0.3", @@ -1697,13 +2105,6 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, - "console-control-strings": { - "version": "1.1.0", - "resolved": false, - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true, - "optional": true - }, "content-disposition": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", @@ -1717,6 +2118,15 @@ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" }, + "continuation-local-storage": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/continuation-local-storage/-/continuation-local-storage-3.2.1.tgz", + "integrity": "sha512-jx44cconVqkCEEyLSKWwkvUXwO561jXMa3LPjTPsm5QR22PA0/mhe33FT4Xb5y74JDvt/Cq+5lm8S8rskLv9ZA==", + "requires": { + "async-listener": "^0.6.0", + "emitter-listener": "^1.1.1" + } + }, "convert-source-map": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", @@ -1762,6 +2172,60 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "cron": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/cron/-/cron-1.7.1.tgz", + "integrity": "sha512-gmMB/pJcqUVs/NklR1sCGlNYM7TizEw+1gebz20BMc/8bTm/r7QUp3ZPSPlG8Z5XRlvb7qhjEjq/+bdIfUCL2A==", + "requires": { + "moment-timezone": "^0.5.x" + } + }, + "cross-env": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-6.0.3.tgz", + "integrity": "sha512-+KqxF6LCvfhWvADcDPqo64yVIB31gv/jQulX2NGzKS/g3GEVz6/pt4wjHFtFWsHMddebWD/sDthJemzM4MaAag==", + "requires": { + "cross-spawn": "^7.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz", + "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -1790,6 +2254,11 @@ "cssom": "0.3.x" } }, + "culvert": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/culvert/-/culvert-0.1.2.tgz", + "integrity": "sha1-lQL18BVKLVoioCPnn3HMk2+m728=" + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -1799,6 +2268,11 @@ "assert-plus": "^1.0.0" } }, + "data-uri-to-buffer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz", + "integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==" + }, "data-urls": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", @@ -1823,12 +2297,17 @@ } } }, + "date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==" + }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "requires": { - "ms": "^2.1.1" + "ms": "2.0.0" } }, "decamelize": { @@ -1842,18 +2321,10 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, - "deep-extend": { - "version": "0.6.0", - "resolved": false, - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, - "optional": true - }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" }, "define-properties": { "version": "1.1.3", @@ -1901,12 +2372,23 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true + } + } + }, + "degenerator": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", + "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", + "requires": { + "ast-types": "0.x.x", + "escodegen": "1.x.x", + "esprima": "3.x.x" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" } } }, @@ -1916,13 +2398,6 @@ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, - "delegates": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true, - "optional": true - }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -1933,23 +2408,26 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, - "detect-libc": { - "version": "1.0.3", - "resolved": false, - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "dev": true, - "optional": true - }, "detect-newline": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", "dev": true }, + "diagnostics": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz", + "integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==", + "requires": { + "colorspace": "1.1.x", + "enabled": "1.0.x", + "kuler": "1.0.x" + } + }, "diff": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz", - "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, "diff-sequences": { @@ -1981,6 +2459,11 @@ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" }, + "double-ended-queue": { + "version": "2.1.0-0", + "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", + "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=" + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -1991,6 +2474,14 @@ "safer-buffer": "^2.1.0" } }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -2005,9 +2496,17 @@ } }, "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "enabled": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", + "integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=", + "requires": { + "env-variable": "0.0.x" + } }, "encodeurl": { "version": "1.0.2", @@ -2036,13 +2535,18 @@ "ws": "^7.1.2" }, "dependencies": { - "ws": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.0.tgz", - "integrity": "sha512-+SqNqFbwTm/0DC18KYzIsMTnEWpLwJsiasW/O17la4iDRRIO9uaHbvKiAS3AHgTiuuWerK/brj4O6MYZkei9xg==", + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "requires": { - "async-limiter": "^1.0.0" + "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==" } } }, @@ -2064,10 +2568,18 @@ "yeast": "0.1.2" }, "dependencies": { - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "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==" }, "ws": { "version": "6.1.4", @@ -2091,6 +2603,19 @@ "has-binary2": "~1.0.2" } }, + "enquirer": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.2.tgz", + "integrity": "sha512-PLhTMPUXlnaIv9D3Cq3/Zr1xb7soeDDgunobyCmYLUG19n24dvC8i+ZZgm2DekGpDnx7JvFSHV7lxfM58PMtbA==", + "requires": { + "ansi-colors": "^3.2.1" + } + }, + "env-variable": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.5.tgz", + "integrity": "sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA==" + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -2101,17 +2626,17 @@ } }, "es-abstract": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.0.tgz", - "integrity": "sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg==", + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.3.tgz", + "integrity": "sha512-WtY7Fx5LiOnSYgF5eg/1T+GONaGmpvpPdCpSnYij+U2gDTL0UPfWrhDw7b2IYb+9NQJsYpCA0wOQvZfsd6YwRw==", "requires": { - "es-to-primitive": "^1.2.0", + "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.0", + "has-symbols": "^1.0.1", "is-callable": "^1.1.4", "is-regex": "^1.0.4", - "object-inspect": "^1.6.0", + "object-inspect": "^1.7.0", "object-keys": "^1.1.1", "string.prototype.trimleft": "^2.1.0", "string.prototype.trimright": "^2.1.0" @@ -2127,11 +2652,29 @@ "is-symbol": "^1.0.2" } }, + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "requires": { + "es6-promise": "^4.0.3" + } + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, + "escape-regexp": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/escape-regexp/-/escape-regexp-0.0.1.tgz", + "integrity": "sha1-9EvaEtRbvfnLf4Yu5+SCez3TIlQ=" + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -2141,7 +2684,6 @@ "version": "1.12.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.12.0.tgz", "integrity": "sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg==", - "dev": true, "requires": { "esprima": "^3.1.3", "estraverse": "^4.2.0", @@ -2150,19 +2692,17 @@ "source-map": "~0.6.1" }, "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" } } }, "eslint": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.6.0.tgz", - "integrity": "sha512-PpEBq7b6qY/qrOmpYQ/jTMDYfuQMELR4g4WI1M/NaSDDD/bdcMb+dj4Hgks7p41kW2caXsPsEZAEAyAgjVVC0g==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.7.2.tgz", + "integrity": "sha512-qMlSWJaCSxDFr8fBPvJM9kJwbazrhNcBU3+DszDW1OlEwKBBRWsJc7NJFelvwQpanHCR14cOLD41x8Eqvo3Nng==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -2180,7 +2720,7 @@ "file-entry-cache": "^5.0.1", "functional-red-black-tree": "^1.0.1", "glob-parent": "^5.0.0", - "globals": "^11.7.0", + "globals": "^12.1.0", "ignore": "^4.0.6", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", @@ -2193,7 +2733,7 @@ "minimatch": "^3.0.4", "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", - "optionator": "^0.8.2", + "optionator": "^0.8.3", "progress": "^2.0.0", "regexpp": "^2.0.1", "semver": "^6.1.2", @@ -2204,11 +2744,47 @@ "v8-compile-cache": "^2.0.3" }, "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 + }, + "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 + }, + "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 + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "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" + } } } }, @@ -2249,10 +2825,9 @@ } }, "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, "esquery": { "version": "1.0.1", @@ -2275,20 +2850,23 @@ "estraverse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" }, "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" }, "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, + "eventemitter2": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-5.0.1.tgz", + "integrity": "sha1-YZegldX7a1folC9v1+qtY6CclFI=" + }, "exec-sh": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.4.tgz", @@ -2331,15 +2909,6 @@ "to-regex": "^3.0.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" - } - }, "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", @@ -2357,12 +2926,6 @@ "requires": { "is-extendable": "^0.1.0" } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true } } }, @@ -2421,32 +2984,13 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" } } }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, "extend-shallow": { "version": "3.0.2", @@ -2542,12 +3086,6 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true } } }, @@ -2572,8 +3110,12 @@ "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "fast-safe-stringify": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", + "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" }, "fb-watchman": { "version": "2.0.0", @@ -2584,6 +3126,16 @@ "bser": "^2.0.0" } }, + "fclone": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fclone/-/fclone-1.0.11.tgz", + "integrity": "sha1-EOhdo4v+p/xZk0HClu4ddyZu5kA=" + }, + "fecha": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", + "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==" + }, "figlet": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.2.4.tgz", @@ -2607,6 +3159,11 @@ "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==" + }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -2642,29 +3199,15 @@ "parseurl": "~1.3.3", "statuses": "~1.5.0", "unpipe": "~1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } } }, "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "requires": { - "locate-path": "^3.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, "flat-cache": { @@ -2676,17 +3219,6 @@ "flatted": "^2.0.0", "rimraf": "2.6.3", "write": "1.0.3" - }, - "dependencies": { - "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": { @@ -2695,6 +3227,24 @@ "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", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "requires": { + "debug": "=3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + } + } + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -2743,16 +3293,6 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, - "fs-minipass": { - "version": "1.2.5", - "resolved": false, - "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2769,132 +3309,614 @@ "node-pre-gyp": "^0.12.0" }, "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": false, + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true, + "optional": true + }, "ansi-regex": { "version": "2.1.1", "resolved": false, - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "optional": true }, - "is-fullwidth-code-point": { - "version": "1.0.0", + "aproba": { + "version": "1.2.0", "resolved": false, - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": false, + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "dev": true, + "optional": true, "requires": { - "number-is-nan": "^1.0.0" + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" } }, - "ms": { - "version": "2.1.1", + "balanced-match": { + "version": "1.0.0", "resolved": false, - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, - "rimraf": { - "version": "2.6.3", + "brace-expansion": { + "version": "1.1.11", "resolved": false, - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "requires": { - "glob": "^7.1.3" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "semver": { - "version": "5.7.0", + "chownr": { + "version": "1.1.1", + "resolved": false, + "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", "resolved": false, - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true, + "optional": true }, - "string-width": { + "concat-map": { + "version": "0.0.1", + "resolved": false, + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true, + "optional": true + }, + "core-util-is": { "version": "1.0.2", "resolved": false, - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true, + "optional": true }, - "strip-ansi": { - "version": "3.0.1", + "debug": { + "version": "4.1.1", "resolved": false, - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "optional": true, "requires": { - "ansi-regex": "^2.0.0" + "ms": "^2.1.1" } }, - "strip-json-comments": { - "version": "2.0.1", + "deep-extend": { + "version": "0.6.0", "resolved": false, - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" - } - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "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 - }, - "gauge": { - "version": "2.7.4", - "resolved": false, - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, "optional": true }, - "is-fullwidth-code-point": { + "delegates": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "resolved": false, + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "resolved": false, + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "resolved": false, + "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", "dev": true, "optional": true, "requires": { - "number-is-nan": "^1.0.0" + "minipass": "^2.2.1" } }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "fs.realpath": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "gauge": { + "version": "2.7.4", + "resolved": false, + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "optional": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" } }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "glob": { + "version": "7.1.3", + "resolved": false, + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "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" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": false, + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": false, + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "optional": true, "requires": { - "ansi-regex": "^2.0.0" + "safer-buffer": ">= 2.1.2 < 3" } - } - } - }, - "get-caller-file": { + }, + "ignore-walk": { + "version": "3.0.1", + "resolved": false, + "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": false, + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": false, + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": false, + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": false, + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": false, + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true, + "optional": true + }, + "minipass": { + "version": "2.3.5", + "resolved": false, + "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "resolved": false, + "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": false, + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "optional": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.1", + "resolved": false, + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true, + "optional": true + }, + "needle": { + "version": "2.3.0", + "resolved": false, + "integrity": "sha512-QBZu7aAFR0522EyaXZM0FZ9GLpq6lvQ3uq8gteiDUp7wKdy0lSd2hPlgFwVuW1CBkfEs9PfDQsQzZghLs/psdg==", + "dev": true, + "optional": true, + "requires": { + "debug": "^4.1.0", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.12.0", + "resolved": false, + "integrity": "sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==", + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "resolved": false, + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.6", + "resolved": false, + "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==", + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.1", + "resolved": false, + "integrity": "sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==", + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": false, + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": false, + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "resolved": false, + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "resolved": false, + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": false, + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "resolved": false, + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": false, + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": false, + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": false, + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": false, + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "resolved": false, + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": false, + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": false, + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "optional": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": false, + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": false, + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": false, + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "resolved": false, + "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "resolved": false, + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "yallist": { + "version": "3.0.3", + "resolved": false, + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "dev": true, + "optional": true + } + } + }, + "ftp": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", + "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", + "requires": { + "readable-stream": "1.1.x", + "xregexp": "2.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "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 + }, + "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==" @@ -2908,6 +3930,19 @@ "pump": "^3.0.0" } }, + "get-uri": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.4.tgz", + "integrity": "sha512-v7LT/s8kVjs+Tx0ykk1I+H/rbpzkHvuIq87LmeXptcf5sNWm9uQiwjNAt94SJPA1zOlCntmnOlJvVWKmzsxG8Q==", + "requires": { + "data-uri-to-buffer": "1", + "debug": "2", + "extend": "~3.0.2", + "file-uri-to-path": "1", + "ftp": "~0.3.10", + "readable-stream": "2" + } + }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", @@ -2923,6 +3958,16 @@ "assert-plus": "^1.0.0" } }, + "git-node-fs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/git-node-fs/-/git-node-fs-1.0.0.tgz", + "integrity": "sha1-SbIV4kLr5Dqkx1Ybu6SZUhdSCA8=" + }, + "git-sha1": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/git-sha1/-/git-sha1-0.1.2.tgz", + "integrity": "sha1-WZrBkrcYdYJeE6RF86bgURjC90U=" + }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -2940,16 +3985,18 @@ "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 + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.3.0.tgz", + "integrity": "sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } }, "graceful-fs": { "version": "4.2.3", @@ -2973,14 +4020,6 @@ "optimist": "^0.6.1", "source-map": "^0.6.1", "uglify-js": "^3.1.4" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } } }, "har-schema": { @@ -3048,16 +4087,9 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" - }, - "has-unicode": { - "version": "2.0.1", - "resolved": false, - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true, - "optional": true + "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==" }, "has-value": { "version": "1.0.0", @@ -3112,21 +4144,33 @@ } }, "http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", "requires": { "depd": "~1.1.2", - "inherits": "2.0.4", + "inherits": "2.0.3", "setprototypeof": "1.1.1", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.0" + } + }, + "http-proxy-agent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "requires": { + "agent-base": "4", + "debug": "3.1.0" }, "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } } } }, @@ -3141,6 +4185,35 @@ "sshpk": "^1.7.0" } }, + "http-status-codes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-1.4.0.tgz", + "integrity": "sha512-JrT3ua+WgH8zBD3HEJYbeEgnuQaAnUeRRko/YojPAJjGmIfGD3KPU/asLdsLwKjfxOmQe5nXMQ0pt/7MyapVbQ==" + }, + "https-proxy-agent": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz", + "integrity": "sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==", + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -3160,32 +4233,14 @@ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, - "ignore-walk": { - "version": "3.0.1", - "resolved": false, - "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, "import-fresh": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz", - "integrity": "sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==", + "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 - } } }, "import-local": { @@ -3225,10 +4280,8 @@ }, "ini": { "version": "1.3.5", - "resolved": false, - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true, - "optional": true + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" }, "inquirer": { "version": "7.0.0", @@ -3251,57 +4304,28 @@ "through": "^2.3.6" }, "dependencies": { - "ansi-escapes": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.2.1.tgz", - "integrity": "sha512-Cg3ymMAdN10wOk/VYfLV7KCQyv7EDirJ64500sU7n9UlmioEtDuU5Gd+hj73hXSU/ex7tHJSssmyftDdkMLO8Q==", - "dev": true, - "requires": { - "type-fest": "^0.5.2" - } - }, "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "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": { - "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" - } - } + "ansi-regex": "^4.1.0" } } } }, + "interpret": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", + "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==" + }, "invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -3311,6 +4335,11 @@ "loose-envify": "^1.0.0" } }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + }, "ipaddr.js": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", @@ -3323,6 +4352,17 @@ "dev": true, "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "is-arrayish": { @@ -3331,6 +4371,14 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "requires": { + "binary-extensions": "^2.0.0" + } + }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -3358,6 +4406,17 @@ "dev": true, "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "is-date-object": { @@ -3393,13 +4452,12 @@ "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 + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + "version": "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==" }, "is-generator-fn": { "version": "2.1.0", @@ -3411,7 +4469,6 @@ "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" } @@ -3423,6 +4480,17 @@ "dev": true, "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "is-plain-object": { @@ -3451,15 +4519,14 @@ "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, "is-symbol": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", - "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", "requires": { - "has-symbols": "^1.0.0" + "has-symbols": "^1.0.1" } }, "is-typedarray": { @@ -3488,8 +4555,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isobject": { "version": "3.0.1", @@ -3567,10 +4633,19 @@ "source-map": "^0.6.1" }, "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "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 } } @@ -3958,14 +5033,6 @@ "mkdirp": "^0.5.1", "slash": "^2.0.0", "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } } }, "jest-validate": { @@ -3995,6 +5062,14 @@ "chalk": "^2.0.1", "jest-util": "^24.9.0", "string-length": "^2.0.0" + }, + "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 + } } }, "jest-worker": { @@ -4018,6 +5093,17 @@ } } }, + "js-git": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/js-git/-/js-git-0.7.8.tgz", + "integrity": "sha1-UvplWrYYd9bxB578ZTS1VPMeVEQ=", + "requires": { + "bodec": "^0.1.0", + "culvert": "^0.1.2", + "git-sha1": "^0.1.2", + "pako": "^0.2.5" + } + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -4031,13 +5117,6 @@ "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" - }, - "dependencies": { - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" - } } }, "jsbn": { @@ -4085,6 +5164,21 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", "dev": true + }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "dev": true + }, + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } } } }, @@ -4141,6 +5235,30 @@ } } }, + "jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -4159,21 +5277,50 @@ "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==", "dev": true }, - "kind-of": { + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", "requires": { - "is-buffer": "^1.1.5" + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" } }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, "kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true }, + "kuler": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz", + "integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==", + "requires": { + "colornames": "^1.1.1" + } + }, + "lazy": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/lazy/-/lazy-1.0.11.tgz", + "integrity": "sha1-2qBoIGKCVCwIgojpdcKXwa53tpA=" + }, "left-pad": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", @@ -4190,7 +5337,6 @@ "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" @@ -4209,19 +5355,67 @@ } }, "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "p-locate": "^4.1.0" } }, "lodash": { "version": "4.17.15", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + }, + "lodash.findindex": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.findindex/-/lodash.findindex-4.6.0.tgz", + "integrity": "sha1-oyRd7mH7m24GJLU1ElYku2nBEQY=" + }, + "lodash.foreach": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", + "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, + "lodash.last": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash.last/-/lodash.last-3.0.0.tgz", + "integrity": "sha1-JC9mMRLdTG5jcoxgo8kJ0b2tvUw=" }, "lodash.memoize": { "version": "4.1.2", @@ -4229,6 +5423,11 @@ "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", "dev": true }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + }, "lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", @@ -4241,6 +5440,30 @@ "integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=", "dev": true }, + "log-driver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", + "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==" + }, + "logform": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.1.2.tgz", + "integrity": "sha512-+lZh4OpERDBLqjiwDLpAWNQu6KMjnlXH2ByZwCuSqVPJletw0kTWJf5CgSNAUKn1KUkv3m2cUz/LK8zyEy7wzQ==", + "requires": { + "colors": "^1.2.1", + "fast-safe-stringify": "^2.0.4", + "fecha": "^2.3.3", + "ms": "^2.1.1", + "triple-beam": "^1.3.0" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "lolex": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.2.0.tgz", @@ -4256,6 +5479,14 @@ "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", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, "make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", @@ -4277,8 +5508,7 @@ "make-error": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", - "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", - "dev": true + "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==" }, "makeerror": { "version": "1.0.11", @@ -4344,14 +5574,6 @@ "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } } }, "mime": { @@ -4360,16 +5582,16 @@ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" }, "mime-db": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" + "version": "1.42.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz", + "integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==" }, "mime-types": { - "version": "2.1.24", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "version": "2.1.25", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.25.tgz", + "integrity": "sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==", "requires": { - "mime-db": "1.40.0" + "mime-db": "1.42.0" } }, "mimic-fn": { @@ -4391,27 +5613,6 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, - "minipass": { - "version": "2.3.5", - "resolved": false, - "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.1", - "resolved": false, - "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, "mixin-deep": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", @@ -4447,6 +5648,24 @@ "integrity": "sha512-wzYSK6R5hRFUu1CIaeKR6iETw+P6657uYWZdC5GPgyjqzV0uBw51TJrQhys0uGAYqwyuKdR1RJqfwD03xU8fVw==", "dev": true }, + "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=" + }, + "moment": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", + "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" + }, + "moment-timezone": { + "version": "0.5.27", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.27.tgz", + "integrity": "sha512-EIKQs7h5sAsjhPCqN6ggx6cEbs94GK050254TIJySD1bzoM5JTYDwAU1IoVOeTOL6Gm27kYJ51/uuvq1kIlrbw==", + "requires": { + "moment": ">= 2.9.0" + } + }, "morgan": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz", @@ -4457,33 +5676,17 @@ "depd": "~1.1.2", "on-finished": "~2.3.0", "on-headers": "~1.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } } }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.0.0", + "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 + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" }, "mysql": { "version": "2.17.1", @@ -4530,14 +5733,6 @@ "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" - }, - "dependencies": { - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } } }, "natural-compare": { @@ -4547,15 +5742,28 @@ "dev": true }, "needle": { - "version": "2.3.0", - "resolved": false, - "integrity": "sha512-QBZu7aAFR0522EyaXZM0FZ9GLpq6lvQ3uq8gteiDUp7wKdy0lSd2hPlgFwVuW1CBkfEs9PfDQsQzZghLs/psdg==", - "dev": true, - "optional": true, + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.4.0.tgz", + "integrity": "sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==", "requires": { - "debug": "^4.1.0", + "debug": "^3.2.6", "iconv-lite": "^0.4.4", "sax": "^1.2.4" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } } }, "negotiator": { @@ -4569,6 +5777,11 @@ "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", "dev": true }, + "netmask": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", + "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=" + }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -4630,35 +5843,10 @@ "which": "^1.3.0" } }, - "node-pre-gyp": { - "version": "0.12.0", - "resolved": false, - "integrity": "sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==", - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "resolved": false, - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } + "nodemailer": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.4.0.tgz", + "integrity": "sha512-UBqPOfQGD1cM3HnjhuQe+0u3DWx47WWK7lBjG5UtPnGOysr7oDK5lNCzcjK6zzeBSdTk4m1tGx1xNbWFZQmMNA==" }, "normalize-package-data": { "version": "2.5.0", @@ -4681,24 +5869,6 @@ "remove-trailing-separator": "^1.0.1" } }, - "npm-bundled": { - "version": "1.0.6", - "resolved": false, - "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==", - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.1", - "resolved": false, - "integrity": "sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==", - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -4708,24 +5878,22 @@ "path-key": "^2.0.0" } }, - "npmlog": { - "version": "4.1.2", - "resolved": false, - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "optional": true, + "nssocket": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/nssocket/-/nssocket-0.6.0.tgz", + "integrity": "sha1-Wflvb/MhVm8zxw99vu7N/cBxVPo=", "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" + "eventemitter2": "~0.4.14", + "lazy": "~1.0.11" + }, + "dependencies": { + "eventemitter2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=" + } } }, - "number-is-nan": { - "version": "1.0.1", - "resolved": false, - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, "nwsapi": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", @@ -4740,7 +5908,7 @@ }, "object-assign": { "version": "4.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-component": { @@ -4767,6 +5935,15 @@ "requires": { "is-descriptor": "^0.1.0" } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -4828,6 +6005,11 @@ "wrappy": "1" } }, + "one-time": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz", + "integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=" + }, "onetime": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", @@ -4851,7 +6033,6 @@ "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", @@ -4861,30 +6042,12 @@ "word-wrap": "~1.2.3" } }, - "os-homedir": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true, - "optional": true - }, "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 }, - "osenv": { - "version": "0.1.5", - "resolved": false, - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, "p-each-series": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", @@ -4909,11 +6072,11 @@ } }, "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==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "requires": { - "p-limit": "^2.0.0" + "p-limit": "^2.2.0" } }, "p-reduce": { @@ -4927,6 +6090,53 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, + "pac-proxy-agent": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-3.0.1.tgz", + "integrity": "sha512-44DUg21G/liUZ48dJpUSjZnFfZro/0K5JTyFYLBcmh9+T6Ooi4/i4efwUiEy0+4oQusCBqWdhv16XohIj1GqnQ==", + "requires": { + "agent-base": "^4.2.0", + "debug": "^4.1.1", + "get-uri": "^2.0.0", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^3.0.0", + "pac-resolver": "^3.0.0", + "raw-body": "^2.2.0", + "socks-proxy-agent": "^4.0.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "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==" + } + } + }, + "pac-resolver": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", + "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", + "requires": { + "co": "^4.6.0", + "degenerator": "^1.0.4", + "ip": "^1.1.5", + "netmask": "^1.0.6", + "thunkify": "^2.1.2" + } + }, + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=" + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -4952,10 +6162,9 @@ } }, "parse5": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", - "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", - "dev": true + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" }, "parse5-htmlparser2-tree-adapter": { "version": "5.1.1", @@ -4963,13 +6172,6 @@ "integrity": "sha512-CF+TKjXqoqyDwHqBhFQ+3l5t83xYi6fVT1tQNg+Ye0JRLnTxWvIroCjEp1A0k4lneHNBGnICUf0cfYVYGEazqw==", "requires": { "parse5": "^5.1.1" - }, - "dependencies": { - "parse5": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", - "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" - } } }, "parseqs": { @@ -5000,9 +6202,9 @@ "dev": true }, "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" }, "path-is-absolute": { "version": "1.0.1", @@ -5018,8 +6220,7 @@ "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" }, "path-to-regexp": { "version": "0.1.7", @@ -5035,34 +6236,239 @@ "pify": "^3.0.0" } }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "picomatch": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.1.1.tgz", + "integrity": "sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA==" + }, + "pidusage": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/pidusage/-/pidusage-2.0.17.tgz", + "integrity": "sha512-N8X5v18rBmlBoArfS83vrnD0gIFyZkXEo7a5pAS2aT0i2OLVymFb2AzVg+v8l/QcXnE1JwZcaXR8daJcoJqtjw==", + "requires": { + "safe-buffer": "^5.1.2" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "pirates": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", + "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", + "dev": true, + "requires": { + "node-modules-regexp": "^1.0.0" + } + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-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" + } + }, + "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 + } + } + }, + "pm2": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/pm2/-/pm2-4.2.1.tgz", + "integrity": "sha512-y75VuMJmMoTgEMSveF4fQGbu3on4YkZXm5Mu4pPW1NlPgdD7yoWu8yfXzAKs94tKCIDrbL54Z5BfFBfUgmFSIw==", + "requires": { + "@pm2/agent": "^0.5.26", + "@pm2/io": "^4.3.2", + "@pm2/js-api": "^0.5.60", + "@pm2/pm2-version-check": "^1.0.3", + "async": "^3.1.0", + "blessed": "0.1.81", + "chalk": "2.4.2", + "chokidar": "^3.2.0", + "cli-table-redemption": "1.0.1", + "commander": "2.15.1", + "cron": "1.7.1", + "date-fns": "1.30.1", + "debug": "4.1.1", + "enquirer": "^2.3.2", + "eventemitter2": "5.0.1", + "fclone": "1.0.11", + "lodash": "4.17.14", + "mkdirp": "0.5.1", + "moment": "2.24.0", + "needle": "2.4.0", + "pidusage": "2.0.17", + "pm2-axon": "3.3.0", + "pm2-axon-rpc": "0.5.1", + "pm2-deploy": "^0.4.0", + "pm2-multimeter": "^0.1.2", + "promptly": "^2", + "ps-list": "6.3.0", + "semver": "^5.5", + "shelljs": "0.8.3", + "source-map-support": "0.5.12", + "sprintf-js": "1.1.2", + "systeminformation": "^4.14.16", + "vizion": "~2.0.2", + "yamljs": "0.3.0" + }, + "dependencies": { + "commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==" + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "lodash": { + "version": "4.17.14", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.14.tgz", + "integrity": "sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "source-map-support": { + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", + "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" + } + } + }, + "pm2-axon": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/pm2-axon/-/pm2-axon-3.3.0.tgz", + "integrity": "sha512-dAFlFYRuFbFjX7oAk41zT+dx86EuaFX/TgOp5QpUKRKwxb946IM6ydnoH5sSTkdI2pHSVZ+3Am8n/l0ocr7jdQ==", + "requires": { + "amp": "~0.3.1", + "amp-message": "~0.1.1", + "debug": "^3.0", + "escape-regexp": "0.0.1" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true + "pm2-axon-rpc": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/pm2-axon-rpc/-/pm2-axon-rpc-0.5.1.tgz", + "integrity": "sha512-hT8gN3/j05895QLXpwg+Ws8PjO4AVID6Uf9StWpud9HB2homjc1KKCcI0vg9BNOt56FmrqKDT1NQgheIz35+sA==", + "requires": { + "debug": "^3.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } }, - "pirates": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", - "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", - "dev": true, + "pm2-deploy": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/pm2-deploy/-/pm2-deploy-0.4.0.tgz", + "integrity": "sha512-3BdCghcGwMKwl3ffHZhc+j5JY5dldH9nq8m/I9W5wehJuSRZIyO96VOgKTMv3hYp7Yk5E+2lRGm8WFNlp65vOA==", "requires": { - "node-modules-regexp": "^1.0.0" + "async": "^2.6", + "tv4": "^1.3" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "requires": { + "lodash": "^4.17.14" + } + } } }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, + "pm2-multimeter": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/pm2-multimeter/-/pm2-multimeter-0.1.2.tgz", + "integrity": "sha1-Gh5VFT1BoFU0zqI8/oYKuqDrSs4=", "requires": { - "find-up": "^3.0.0" + "charm": "~0.1.1" } }, "pn": { @@ -5080,8 +6486,7 @@ "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" }, "pretty-format": { "version": "24.9.0", @@ -5093,12 +6498,20 @@ "ansi-regex": "^4.0.0", "ansi-styles": "^3.2.0", "react-is": "^16.8.4" + }, + "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 + } } }, "process-nextick-args": { - "version": "2.0.0", - "resolved": false, - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "progress": { "version": "2.0.3", @@ -5106,6 +6519,14 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, + "promptly": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/promptly/-/promptly-2.2.0.tgz", + "integrity": "sha1-KhP6BjaIoqWYOxYf/wEIoH0m/HQ=", + "requires": { + "read": "^1.0.4" + } + }, "prompts": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.3.0.tgz", @@ -5125,10 +6546,50 @@ "ipaddr.js": "1.9.0" } }, + "proxy-agent": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.1.1.tgz", + "integrity": "sha512-WudaR0eTsDx33O3EJE16PjBRZWcX8GqCEeERw1W3hZJgH/F2a46g7jty6UGty6NeJ4CKQy8ds2CJPMiyeqaTvw==", + "requires": { + "agent-base": "^4.2.0", + "debug": "4", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^3.0.0", + "lru-cache": "^5.1.1", + "pac-proxy-agent": "^3.0.1", + "proxy-from-env": "^1.0.0", + "socks-proxy-agent": "^4.0.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "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==" + } + } + }, + "proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=" + }, + "ps-list": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/ps-list/-/ps-list-6.3.0.tgz", + "integrity": "sha512-qau0czUSB0fzSlBOQt0bo+I2v6R+xiQdj78e1BR/Qjfl5OHWJ/urXi8+ilw1eHe+5hSeDI1wrwVTgDp2wst4oA==" + }, "psl": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.4.0.tgz", - "integrity": "sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.5.0.tgz", + "integrity": "sha512-4vqUjKi2huMu1OJiLhi3jN6jeeKvMZdI1tYgi/njW5zV52jNLgSAZSdN16m9bJFe61/cT8ulmw4qFitV9QRsEA==", "dev": true }, "pump": { @@ -5148,10 +6609,9 @@ "dev": true }, "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" }, "range-parser": { "version": "1.2.1", @@ -5167,57 +6627,22 @@ "http-errors": "1.7.2", "iconv-lite": "0.4.24", "unpipe": "1.0.0" - }, - "dependencies": { - "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - } - } - }, - "rc": { - "version": "1.2.8", - "resolved": false, - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": false, - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true, - "optional": true - }, - "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, - "optional": true - } } }, "react-is": { - "version": "16.11.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.11.0.tgz", - "integrity": "sha512-gbBVYR2p8mnriqAwWx9LbuUrShnAuSCNnuPGyc7GJrMVQtPDAh8iLpv7FRuMPFb56KkaVZIYSz1PrjI9q0QPCw==", + "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": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "requires": { + "mute-stream": "~0.0.4" + } + }, "read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", @@ -5237,11 +6662,47 @@ "requires": { "find-up": "^3.0.0", "read-pkg": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-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" + } + }, + "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 + } } }, "readable-stream": { "version": "2.3.6", - "resolved": false, + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { "core-util-is": "~1.0.0", @@ -5253,6 +6714,14 @@ "util-deprecate": "~1.0.1" } }, + "readdirp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", + "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", + "requires": { + "picomatch": "^2.0.4" + } + }, "realpath-native": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", @@ -5262,6 +6731,34 @@ "util.promisify": "^1.0.0" } }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "requires": { + "resolve": "^1.1.6" + } + }, + "redis": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", + "integrity": "sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==", + "requires": { + "double-ended-queue": "^2.1.0-0", + "redis-commands": "^1.2.0", + "redis-parser": "^2.6.0" + } + }, + "redis-commands": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.5.0.tgz", + "integrity": "sha512-6KxamqpZ468MeQC3bkWmCB1fp56XL64D4Kf0zJSwDZbVLLm7KFkoIcHrgRvQ+sk8dnhySs7+yBg94yIkAK7aJg==" + }, + "redis-parser": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz", + "integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=" + }, "reflect-metadata": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", @@ -5278,9 +6775,9 @@ } }, "regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.0.0.tgz", + "integrity": "sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g==", "dev": true }, "remove-trailing-separator": { @@ -5335,6 +6832,12 @@ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "dev": true }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, "tough-cookie": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", @@ -5372,16 +6875,40 @@ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, + "require-in-the-middle": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-5.0.2.tgz", + "integrity": "sha512-l2r6F9i6t5xp4OE9cw/daB/ooQKHZOOW1AYPADhEvk/Tj/THJDS8gePp76Zyuht6Cj57a0KL+eHK5Dyv7wZnKA==", + "requires": { + "debug": "^4.1.1", + "module-details-from-path": "^1.0.3", + "resolve": "^1.12.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "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==" + } + } + }, "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==" }, "resolve": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", - "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", - "dev": true, + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.13.1.tgz", + "integrity": "sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w==", "requires": { "path-parse": "^1.0.6" } @@ -5393,12 +6920,20 @@ "dev": true, "requires": { "resolve-from": "^3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + } } }, "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "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 }, "resolve-url": { @@ -5424,9 +6959,9 @@ "dev": true }, "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "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" @@ -5530,21 +7065,6 @@ "statuses": "~1.5.0" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", @@ -5611,6 +7131,16 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, + "shelljs": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", + "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, "shellwords": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", @@ -5625,8 +7155,22 @@ "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "requires": { + "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + } + } }, "sinon": { "version": "7.5.0", @@ -5641,14 +7185,6 @@ "lolex": "^4.2.0", "nise": "^1.5.2", "supports-color": "^5.5.0" - }, - "dependencies": { - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - } } }, "sisteransi": { @@ -5672,8 +7208,21 @@ "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 + } } }, + "smart-buffer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz", + "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==" + }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -5690,15 +7239,6 @@ "use": "^3.1.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" - } - }, "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", @@ -5717,10 +7257,10 @@ "is-extendable": "^0.1.0" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true } } @@ -5773,12 +7313,6 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true } } }, @@ -5789,6 +7323,17 @@ "dev": true, "requires": { "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "socket.io": { @@ -5802,6 +7347,21 @@ "socket.io-adapter": "~1.1.0", "socket.io-client": "2.3.0", "socket.io-parser": "~3.4.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "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==" + } } }, "socket.io-adapter": { @@ -5830,10 +7390,13 @@ "to-array": "0.1.4" }, "dependencies": { - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } }, "isarray": { "version": "2.0.1", @@ -5841,9 +7404,9 @@ "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "socket.io-parser": { "version": "3.3.0", @@ -5862,6 +7425,11 @@ "requires": { "ms": "2.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } } @@ -5877,23 +7445,58 @@ "isarray": "2.0.1" }, "dependencies": { - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } }, "isarray": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "socks": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.3.tgz", + "integrity": "sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==", + "requires": { + "ip": "1.1.5", + "smart-buffer": "^4.1.0" + } + }, + "socks-proxy-agent": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz", + "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==", + "requires": { + "agent-base": "~4.2.1", + "socks": "~2.3.2" + }, + "dependencies": { + "agent-base": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", + "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", + "requires": { + "es6-promisify": "^5.0.0" + } } } }, "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-resolve": { "version": "0.5.2", @@ -5912,18 +7515,9 @@ "version": "0.5.16", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", - "dev": true, "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } } }, "source-map-url": { @@ -6005,6 +7599,11 @@ "resolved": "https://registry.npmjs.org/stack-chain/-/stack-chain-1.3.7.tgz", "integrity": "sha1-0ZLJ/06moiyUxN1FkXHj8AzqEoU=" }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + }, "stack-utils": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz", @@ -6071,13 +7670,13 @@ } }, "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==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" } }, "string.prototype.trimleft": { @@ -6100,18 +7699,18 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { "safe-buffer": "~5.1.0" } }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^5.0.0" } }, "strip-bom": { @@ -6158,6 +7757,12 @@ "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 } } }, @@ -6185,6 +7790,12 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, + "systeminformation": { + "version": "4.16.0", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-4.16.0.tgz", + "integrity": "sha512-1FjxPJSw7ad0zug+1YIQATj6Cn+wM5OBASEpjohEeOD2EGPIf0Cnhthd1L2O1YX+wKgOMuPldGfxYdo8yNHEIg==", + "optional": true + }, "table": { "version": "5.4.6", "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", @@ -6195,22 +7806,46 @@ "lodash": "^4.17.14", "slice-ansi": "^2.1.0", "string-width": "^3.0.0" - } - }, - "tar": { - "version": "4.4.8", - "resolved": false, - "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" + }, + "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 + }, + "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" + } + }, + "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" + } + } } }, "test-exclude": { @@ -6225,6 +7860,11 @@ "require-main-filename": "^2.0.0" } }, + "text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -6259,6 +7899,11 @@ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, + "thunkify": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", + "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=" + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -6292,6 +7937,17 @@ "dev": true, "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "to-regex": { @@ -6340,10 +7996,15 @@ "punycode": "^2.1.0" } }, + "triple-beam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", + "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" + }, "ts-jest": { - "version": "24.1.0", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-24.1.0.tgz", - "integrity": "sha512-HEGfrIEAZKfu1pkaxB9au17b1d9b56YZSqz5eCVE8mX68+5reOvlM93xGOzzCREIov9mdH7JBG+s0UyNAqr0tQ==", + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-24.2.0.tgz", + "integrity": "sha512-Yc+HLyldlIC9iIK8xEN7tV960Or56N49MDP7hubCZUeI7EbIOTsas6rXCMB4kQjLACJ7eDOF4xWEO5qumpKsag==", "dev": true, "requires": { "bs-logger": "0.x", @@ -6376,16 +8037,22 @@ } }, "ts-node": { - "version": "8.5.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.5.2.tgz", - "integrity": "sha512-W1DK/a6BGoV/D4x/SXXm6TSQx6q3blECUzd5TN+j56YEMX3yPVMpHsICLedUw3DvGF3aTQ8hfdR9AKMaHjIi+A==", - "dev": true, + "version": "8.5.4", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.5.4.tgz", + "integrity": "sha512-izbVCRV68EasEPQ8MSIGBNK9dc/4sYJJKYA+IarMQct1RtEot6Xp0bXuClsbUSnKpg50ho+aOAx8en5c+y4OFw==", "requires": { "arg": "^4.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", "source-map-support": "^0.5.6", "yn": "^3.0.0" + }, + "dependencies": { + "diff": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz", + "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==" + } } }, "tsconfig-paths": { @@ -6440,6 +8107,11 @@ "safe-buffer": "^5.0.1" } }, + "tv4": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tv4/-/tv4-1.3.0.tgz", + "integrity": "sha1-0CDIRvrdUMhVq7JeuuzGj8EPeWM=" + }, "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", @@ -6450,7 +8122,6 @@ "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" } @@ -6462,9 +8133,9 @@ "dev": true }, "type-fest": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.5.2.tgz", - "integrity": "sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw==", + "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": { @@ -6497,55 +8168,64 @@ "yargs": "^13.2.1" }, "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, "dotenv": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz", "integrity": "sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" } } }, "typeorm-test-transactions": { - "version": "github:raccoonback/typeorm-test-transactions#b5319e14d9e635b8607f45f26639f2294d424b3d", - "from": "github:raccoonback/typeorm-test-transactions#master", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/typeorm-test-transactions/-/typeorm-test-transactions-1.3.0.tgz", + "integrity": "sha512-C0dgdCFGfHybgja67KYqroV59dr0YrIX/nyT3lrfmN9WujlJkgTFVdacXv1AmXoou7eQCCT9oT2y6Mg0fB6Uqg==", "dev": true, "requires": { "typeorm-transactional-cls-hooked": "^0.1.8" } }, "typeorm-transactional-cls-hooked": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/typeorm-transactional-cls-hooked/-/typeorm-transactional-cls-hooked-0.1.8.tgz", - "integrity": "sha512-JNBuwThSNKbtT2CB6C5ZrwBgXLvzteNJQbAxqwHyJIEDTc/h4CSpRuN+8dHiJVI4Eq4wmbOrk720rvjhucIbYQ==", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/typeorm-transactional-cls-hooked/-/typeorm-transactional-cls-hooked-0.1.10.tgz", + "integrity": "sha512-uQ1w0Ms5ywYD8w1FxPHPy9mPFioLlhMcAEfvQxKAgIu2Twyc5qxRjWEJ4O2sz1VJEvXCmzoremP6yg4Ttd1SIg==", "requires": { "cls-hooked": "^4.2.2" } }, "typescript": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.2.tgz", - "integrity": "sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ==", - "dev": true + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.3.tgz", + "integrity": "sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw==" }, "uglify-js": { - "version": "3.6.9", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.9.tgz", - "integrity": "sha512-pcnnhaoG6RtrvHJ1dFncAe8Od6Nuy30oaJ82ts6//sGSXOP5UjBMEthiProjXmMNHOfd93sqlkztifFMcb+4yw==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.7.1.tgz", + "integrity": "sha512-pnOF7jY82wdIhATVn87uUY/FHU+MDUdPLkmGFvGoclQmeu229eTkbG5gjGGBi3R7UuYYSEeYXY/TTY5j2aym2g==", "dev": true, "optional": true, "requires": { "commander": "~2.20.3", "source-map": "~0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true - } } }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" + }, "union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", @@ -6626,7 +8306,7 @@ }, "util-deprecate": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "util.promisify": { @@ -6646,8 +8326,7 @@ "uuid": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", - "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==", - "dev": true + "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" }, "v8-compile-cache": { "version": "2.1.0", @@ -6681,6 +8360,31 @@ "extsprintf": "^1.2.0" } }, + "vizion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/vizion/-/vizion-2.0.2.tgz", + "integrity": "sha512-UGDB/UdC1iyPkwyQaI9AFMwKcluQyD4FleEXObrlu254MEf16MV8l+AZdpFErY/iVKZVWlQ+OgJlVVJIdeMUYg==", + "requires": { + "async": "2.6.1", + "git-node-fs": "^1.0.0", + "ini": "^1.3.4", + "js-git": "^0.7.8", + "lodash.findindex": "^4.6.0", + "lodash.foreach": "^4.5.0", + "lodash.get": "^4.4.2", + "lodash.last": "^3.0.0" + }, + "dependencies": { + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "requires": { + "lodash": "^4.17.10" + } + } + } + }, "w3c-hr-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", @@ -6745,51 +8449,55 @@ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, - "wide-align": { - "version": "1.1.3", - "resolved": false, - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "optional": true, + "winston": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.2.1.tgz", + "integrity": "sha512-zU6vgnS9dAWCEKg/QYigd6cgMVVNwyTzKs81XZtTFuRwJOcDdBg7AU0mXVyNbs7O5RH2zdv+BdNZUlx7mXPuOw==", "requires": { - "string-width": "^1.0.2 || 2" + "async": "^2.6.1", + "diagnostics": "^1.1.1", + "is-stream": "^1.1.0", + "logform": "^2.1.1", + "one-time": "0.0.4", + "readable-stream": "^3.1.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.3.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, - "optional": 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, - "optional": true, + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "lodash": "^4.17.14" } }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "optional": true, + "readable-stream": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", + "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", "requires": { - "ansi-regex": "^3.0.0" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" } } } }, + "winston-transport": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.3.0.tgz", + "integrity": "sha512-B2wPuwUi3vhzn/51Uukcao4dIduEiPOcOt9HJ3QeaXgkJ5Z7UwpBzxS4ZGNHtrxrUvTwemsQiSys0ihOf8Mp1A==", + "requires": { + "readable-stream": "^2.3.6", + "triple-beam": "^1.2.0" + } + }, "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 + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" }, "wordwrap": { "version": "0.0.3", @@ -6798,13 +8506,37 @@ "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==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.0.tgz", + "integrity": "sha512-7kFQgnEaMdRtwf6uSfUnVr9gSGC7faurn+J/Mv90/W+iTtN0405/nLdopfMWwchyxhbGYl6TC4Sccn9TUkGAgg==", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + } } }, "wrappy": { @@ -6833,12 +8565,11 @@ } }, "ws": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", - "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", - "dev": true, + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.0.tgz", + "integrity": "sha512-+SqNqFbwTm/0DC18KYzIsMTnEWpLwJsiasW/O17la4iDRRIO9uaHbvKiAS3AHgTiuuWerK/brj4O6MYZkei9xg==", "requires": { - "async-limiter": "~1.0.0" + "async-limiter": "^1.0.0" } }, "xml-name-validator": { @@ -6867,17 +8598,29 @@ "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=" }, + "xregexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", + "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=" + }, "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==" }, "yallist": { - "version": "3.0.3", - "resolved": false, - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true, - "optional": true + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "yamljs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/yamljs/-/yamljs-0.3.0.tgz", + "integrity": "sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==", + "requires": { + "argparse": "^1.0.7", + "glob": "^7.0.5" + } }, "yargonaut": { "version": "1.1.4", @@ -6941,12 +8684,106 @@ "which-module": "^2.0.0", "y18n": "^4.0.0", "yargs-parser": "^13.1.1" + }, + "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==" + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "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=" + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "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==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "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==", + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } } }, "yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-16.1.0.tgz", + "integrity": "sha512-H/V41UNZQPkUMIT5h5hiwg4QKIY1RPvoBV4XcjUbRM8Bk2oKqqyZ0DIEbTFZB0XjbtSPG8SAa/0DxCQmiRgzKg==", "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" @@ -6960,8 +8797,7 @@ "yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==" } } } diff --git a/server/package.json b/server/package.json index d672b775..e3f04b6a 100644 --- a/server/package.json +++ b/server/package.json @@ -3,45 +3,59 @@ "version": "1.0.0", "private": true, "scripts": { - "serve": "tsc && node dist/app.js", + "serve": "npm run build && cross-env NODE_ENV=production pm2 dist/server.js -i 0", + "build": "tsc", "test": "jest", "lint": "eslint src/**/*.ts", - "start": "ts-node src/server.ts", - "typeorms": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js" + "start": "cross-env NODE_ENV=local ts-node src/server.ts", + "typeorms": "NODE_ENV=local ts-node ./node_modules/typeorm/cli.js" }, "dependencies": { - "@types/socket.io": "^2.1.4", + "bcryptjs": "^2.4.3", "cookie-parser": "^1.4.4", + "cross-env": "^6.0.3", "dotenv": "^8.2.0", "express": "^4.17.1", + "http-status-codes": "^1.4.0", + "jsonwebtoken": "^8.5.1", + "lodash": "^4.17.15", "morgan": "^1.9.1", "mysql": "^2.14.1", + "nodemailer": "^6.3.1", + "pm2": "^4.2.1", + "redis": "^2.8.0", "reflect-metadata": "^0.1.10", "socket.io": "^2.3.0", + "ts-node": "^8.5.2", "typeorm": "^0.2.20", - "typeorm-transactional-cls-hooked": "^0.1.8" + "typeorm-transactional-cls-hooked": "^0.1.8", + "typescript": "^3.7.2", + "winston": "^3.2.1" }, "devDependencies": { + "@types/bcryptjs": "^2.4.2", "@types/cookie-parser": "^1.4.2", - "@types/errorhandler": "0.0.32", "@types/eslint": "^6.1.3", "@types/express": "^4.17.2", "@types/jest": "^24.0.22", + "@types/jsonwebtoken": "^8.3.5", + "@types/lodash": "^4.14.149", + "@types/mock-req-res": "^1.1.0", "@types/morgan": "^1.7.37", - "@types/node": "^8.0.29", + "@types/node": "^12.12.14", + "@types/nodemailer": "^6.2.2", + "@types/socket.io": "^2.1.4", "@types/supertest": "^2.0.8", + "@types/winston": "^2.4.4", "@typescript-eslint/eslint-plugin": "^2.7.0", "@typescript-eslint/parser": "^2.7.0", - "@types/mock-req-res": "^1.1.0", "eslint": "^6.6.0", "jest": "^24.9.0", + "mock-req-res": "^1.1.3", + "sinon": "^7.5.0", "supertest": "^4.0.2", "ts-jest": "^24.1.0", - "ts-node": "^8.5.2", "tsconfig-paths": "^3.9.0", - "typeorm-test-transactions": "github:raccoonback/typeorm-test-transactions#master", - "typescript": "^3.7.2", - "mock-req-res": "^1.1.3", - "sinon": "^7.5.0" + "typeorm-test-transactions": "^1.3.0" } } diff --git a/server/public/image/default-thumbnail.jpeg b/server/public/image/default-thumbnail.jpeg new file mode 100644 index 00000000..e3e26f54 Binary files /dev/null and b/server/public/image/default-thumbnail.jpeg differ diff --git a/server/src/app.ts b/server/src/app.ts index d6ffff8b..a0b3b36d 100644 --- a/server/src/app.ts +++ b/server/src/app.ts @@ -1,20 +1,33 @@ -import "dotenv/config"; +import dotenv from "dotenv"; import "reflect-metadata"; -import express, { Express } from "express"; +import express, {Express} from "express"; import morgan from "morgan"; +import hpp from "hpp"; +import helmet from "helmet"; import cookieParser from "cookie-parser"; +import apiRouter from "./routes/apiRouter"; +import indexRouter from "./routes/index"; +import { + notFoundHandler, + errorResopnseHandler +} from "./middleware/errorHandler"; import { Connection, createConnection } from "typeorm"; -import postRouter from "./routes/post/post-router"; -import channelRouter from "./routes/channel/channel-router"; +import { + initializeTransactionalContext, + patchTypeORMRepositoryWithBaseRepository +} from "typeorm-transactional-cls-hooked"; export default class App { private static app: Express; private static connection: Connection; static async start() { + const envPath = __dirname.concat("/../.env." + process.env.NODE_ENV!); + dotenv.config({ path: envPath }); return await createConnection() .then(connection => { this.connection = connection; + this.setUpTransactions(); return this.initializeExpress(); }) .catch(error => console.error("TypeORM Connection Error: ", error)); @@ -24,16 +37,32 @@ export default class App { this.app = express(); this.app.set("port", process.env.PORT || 3000); this.app.set("env", process.env.NODE_ENV); - this.app.use(morgan("dev")); + if (process.env.NODE_ENV === "production") { + this.app.use(morgan("combined")); + this.app.use(helmet()); + this.app.use(hpp()); + } else { + this.app.use(morgan("dev")); + } + + this.app.use(express.static("/")); this.app.use(express.json()); this.app.use(express.urlencoded({ extended: false })); this.app.use(cookieParser(process.env.COOKIE_SECRET)); - this.app.use("/api/posts", postRouter); - this.app.use("/api/channels", channelRouter); + this.app.use("/api", apiRouter); + this.app.use("/", indexRouter); + this.app.use(notFoundHandler); + this.app.use(errorResopnseHandler); + return this.app; } static getEntityManager() { return this.connection.manager; } -} \ No newline at end of file + + static setUpTransactions(): void { + initializeTransactionalContext(); + patchTypeORMRepositoryWithBaseRepository(); + } +} diff --git a/server/src/controller/api/auth-controller.ts b/server/src/controller/api/auth-controller.ts new file mode 100644 index 00000000..e8f337c6 --- /dev/null +++ b/server/src/controller/api/auth-controller.ts @@ -0,0 +1,66 @@ +import { User } from "../../domain/entity/User"; +import { Email } from "../../domain/vo/Email"; +import { Request, Response } from "express"; +import {NOT_FOUND, OK, UNAUTHORIZED} from "http-status-codes"; +import ResponseForm from "../../utils/response-form"; +import * as crypto from "bcryptjs"; +import { offerTokenInfo } from "../../validator/identifier-validator"; +import { Profile } from "../../domain/entity/Profile"; +import { Token } from "./common/token/token"; +import { UserToken } from "./common/token/user-token"; +import { ProfileToken } from "./common/token/profile-token"; +import { ProfileInfo } from "../../model/profile/profile-info"; +import { + INVALID_USER_EMAIL, + INVALID_USER_PASSWORD, NOT_EXIST_USER_OR_SNUG, + SUCCESS_GENERATE_PROFILE_TOKEN, + SUCCESS_GENERATE_USER_TOKEN +} from "./common/messages"; + +type bodyType = { + email: string; + password: string; +}; + +export const login = async ( + request: Request, + response: Response +): Promise => { + try { + const { email, password }: bodyType = request.body; + const emailModel = Email.from(email); + const user = await User.findOne({ where: { email: emailModel } }); + if (!crypto.compareSync(password, user.password)) { + return response.status(UNAUTHORIZED).json(ResponseForm.of(INVALID_USER_PASSWORD)); + } + + const userToken: Token = new UserToken(); + return response + .status(OK) + .json( + ResponseForm.of(SUCCESS_GENERATE_USER_TOKEN, { token: userToken.tokenize(user) }) + ); + } catch (error) { + return response.status(NOT_FOUND).json(ResponseForm.of(INVALID_USER_EMAIL)); + } +}; + +export const getProfileToken = async ( + request: Request, + response: Response +): Promise => { + const { snugId } = request.params; + try { + const { id } = offerTokenInfo(request); + const userId = id.toString(); + const profile = await Profile.findOneByUserIdAndSnugId(userId, snugId); + const profileInfo = ProfileInfo.fromProfile(profile); + const profileToken: Token = new ProfileToken(); + return response + .status(OK) + .cookie("profile", profileToken.tokenize(profileInfo)) + .json(ResponseForm.of(SUCCESS_GENERATE_PROFILE_TOKEN)); + } catch (error) { + return response.status(NOT_FOUND).json(ResponseForm.of(NOT_EXIST_USER_OR_SNUG)); + } +}; diff --git a/server/src/controller/api/channel-controller.ts b/server/src/controller/api/channel-controller.ts index 0f431d98..927b9a67 100644 --- a/server/src/controller/api/channel-controller.ts +++ b/server/src/controller/api/channel-controller.ts @@ -1,15 +1,27 @@ -import {Room} from "../../entity/Room"; -import {NextFunction, Request, Response} from "express"; +import { Participant } from "./../../model/participant/participant"; +import { Profile } from "./../../domain/entity/Profile"; +import { ParticipateIn } from "./../../domain/entity/ParticipateIn"; +import { offerProfileTokenInfo } from "./../../validator/identifier-validator"; +import { Room } from "../../domain/entity/Room"; +import { NextFunction, Request, Response } from "express"; import ResponseForm from "../../utils/response-form"; -import {CONFLICT, CREATED, INTERNAL_SERVER_ERROR, NOT_FOUND, OK} from "./common/status-code"; +import { + CONFLICT, + CREATED, + INTERNAL_SERVER_ERROR, + NOT_FOUND, + OK +} from "http-status-codes"; import { ALREADY_EXIST_CHANNEL, CREATE_CHANNEL, FOUND_CHANNEL, FOUND_CHANNELS, - NOT_FOUND_CHANNEL, NOT_FOUND_CHANNELS -} from "./common/error-message"; -import HttpException from "../../util/HttpException"; + NOT_FOUND_CHANNEL, + NOT_FOUND_CHANNELS +} from "./common/messages"; +import HttpException from "../../utils/exception/HttpException"; +import { Snug } from "../../domain/entity/Snug"; /** * @@ -23,23 +35,32 @@ export const find = async (request: Request, response: Response) => { const title = request.params.title; const channel = await Room.findByTitle(title); if (!!channel) { - return response.status(OK).json(ResponseForm.of(FOUND_CHANNEL, channel)); + return response + .status(OK) + .json(ResponseForm.of(FOUND_CHANNEL, channel)); } else { return response.status(NOT_FOUND).json(ResponseForm.of(NOT_FOUND_CHANNEL)); } }; -export const findAll = async (request: Request, response: Response, next: NextFunction) => { +export const findAll = async ( + request: Request, + response: Response, + next: NextFunction +) => { try { - const channels = await Room.find(); + const { snugId } = request.params; + const exSnug = await Snug.findOne({ where: { id: snugId } }); + + const channels = await Room.find({ where: { snug: exSnug } }); if (!!channels) { return response - .status(OK) - .json(ResponseForm.of(FOUND_CHANNELS, channels)); + .status(OK) + .json(ResponseForm.of(FOUND_CHANNELS, channels)); } else { next(new HttpException(NOT_FOUND_CHANNELS, NOT_FOUND)); } - } catch (error){ + } catch (error) { next(new HttpException(error.message, INTERNAL_SERVER_ERROR)); } }; @@ -54,22 +75,47 @@ export const findAll = async (request: Request, response: Response, next: NextFu * * */ export const create = async (request: Request, response: Response) => { - const title = request.body.title; - const description = request.body.description; - const privacy = request.body.privacy; + const { title, description, privacy, snugId } = request.body; + + const profile = offerProfileTokenInfo(request); const isExisting = await Room.findByTitle(title); if (!!isExisting) { - return response.status(CONFLICT).json(ResponseForm.of(ALREADY_EXIST_CHANNEL)); + return response + .status(CONFLICT) + .json(ResponseForm.of(ALREADY_EXIST_CHANNEL)); } - + const snug = await Snug.findOne({ where: { id: snugId } }); const channel = await Room.create({ title: title, description: description, isPrivate: privacy, - isChannel: true + isChannel: true, + snug: snug + }).save(); + + await ParticipateIn.create({ + room: { id: channel.id }, + participant: { id: profile.id } }).save(); - return response.status(CREATED).json(ResponseForm.of(CREATE_CHANNEL, channel)); -}; \ No newline at end of file + return response + .status(CREATED) + .json(ResponseForm.of(CREATE_CHANNEL, channel)); +}; + +export const join = async (request: Request, response: Response) => { + try { + const payload: any = offerProfileTokenInfo(request); + const { channelId } = request.body; + const result = await ParticipateIn.create({ + room: { id: channelId }, + participant: { id: payload.id } + }).save(); + if (!result) throw new Error("조인실패"); + response.status(OK).json(ResponseForm.of("성공", result)); + } catch (error) { + response.status(NOT_FOUND).json(ResponseForm.of(error.message)); + } +}; diff --git a/server/src/controller/api/common/error-message.ts b/server/src/controller/api/common/error-message.ts deleted file mode 100644 index 93c3a967..00000000 --- a/server/src/controller/api/common/error-message.ts +++ /dev/null @@ -1,15 +0,0 @@ -export const FOUND_CHANNEL = "found channel"; - -export const NOT_FOUND_CHANNEL = "not found channel, you must right channel title"; - -export const CREATE_CHANNEL = "create new channel"; - -export const FOUND_CHANNELS = "found channel list"; - -export const NOT_FOUND_CHANNELS = "not found channel list"; - -export const FOUND_POST_PROFILE = "found post with profile"; - -export const NOT_FOUND_PROFILE = "not found profile, you must right profile id"; - -export const ALREADY_EXIST_CHANNEL="given channel title already exists"; diff --git a/server/src/controller/api/common/messages.ts b/server/src/controller/api/common/messages.ts new file mode 100644 index 00000000..c7b89420 --- /dev/null +++ b/server/src/controller/api/common/messages.ts @@ -0,0 +1,58 @@ +export const FOUND_CHANNEL = "found channel"; + +export const NOT_FOUND_CHANNEL = + "not found channel, you must right channel title"; + +export const CREATE_CHANNEL = "create new channel"; + +export const FOUND_CHANNELS = "found channel list"; + +export const NOT_FOUND_CHANNELS = "not found channel list"; + +export const FOUND_POST_PROFILE = "found post with profile"; + +export const NOT_FOUND_PROFILE = "not found profile, you must right profile id"; + +export const ALREADY_EXIST_CHANNEL = "given channel title already exists"; + +export const CREATE_USER_SUCCESSFULLY = "created user successfully"; + +export const FOUND_EMAIL_USER = "found user with this email"; + +export const NO_USER_WITH_EMAIL = "no user with this email"; + +export const CREATED_SNUG = "snug was created"; + +export const OK_SNUG = "found snug"; + +export const SUCCESS_INVITE="successfully sent all your emails and alarm"; + +export const NOT_FOUND="not found snug. you should give invalid snug id"; + +export const FOUND_INVITATIONS="found invitations list about invitee"; + +export const UNSUPPORTED_EMAIL = "find out invalid invite email"; + +export const SUCCESS_JOIN_SNUG = "successfully join snug through invitation ticket"; + +export const SUCCESS_REJECT_INVITATION_SNUG = "successfully reject invitation snug through ticket"; + +export const ALREADY_JOINED_SNUG ="already joined snug, you cannot join through this ticket"; + +export const INVALID_TICKET = "reject request because invalid ticket"; + +export const INACCESSIBLE_PROFILE = "cannot accessible profile, because you do not have permission for that profile"; + +export const SUCCESS_UPDATE_PROFILE = "successfully update profile"; + +export const SUCCESS_FIND_PROFILE = "successfully find profile"; + +export const SUCCESS_GENERATE_USER_TOKEN = "successfully generate user token through user id, password"; + +export const SUCCESS_GENERATE_PROFILE_TOKEN = "successfully generate profile token about snug"; + +export const INVALID_USER_EMAIL = "not suitable email"; + +export const INVALID_USER_PASSWORD = "not suitable password"; + +export const NOT_EXIST_USER_OR_SNUG = "does not exist snug or user"; \ No newline at end of file diff --git a/server/src/controller/api/common/order.ts b/server/src/controller/api/common/order.ts index c1cd8894..d5711201 100644 --- a/server/src/controller/api/common/order.ts +++ b/server/src/controller/api/common/order.ts @@ -42,7 +42,7 @@ export class Order { * */ add(key: string, value: string): Order { if(this.has(key)) { - const sort = SORT[value] || SORT.ASC; + const sort = SORT[value] || SORT.DESC; this.entries.push({key: key, value: sort}); } diff --git a/server/src/controller/api/common/pagenation/paginator.ts b/server/src/controller/api/common/pagenation/paginator.ts new file mode 100644 index 00000000..76bf6143 --- /dev/null +++ b/server/src/controller/api/common/pagenation/paginator.ts @@ -0,0 +1,56 @@ +import {Order} from "../order"; +import {Page} from "./strategy/page"; +import {DefaultPage} from "./strategy/default-page"; +import _ from "lodash"; + +/** + * + * TypeORM 의 Pagination 기능을 지원하는 객체 + * + */ +export class Paginator { + private readonly page: Page; + private readonly order: Order; + private options: object; + + constructor(page: Page) { + this.page = page || new DefaultPage(); + this.order = new Order(); + } + + /** + * + * 특정 칼럼에 대한 정렬 조건을 Order 객체에 저장 + * + * @param key Column + * @param value SORT (ex, ASC/DESC) + * @return itself(Pageable) + * + */ + addOrder(key: string, value: string): Paginator { + this.order.add(key, value); + return this; + } + + /** + * + * options, page, Order 기반으로 TypeORM 옵션 지원 + * + * @return TypeORM 옵션인 page, size, order 포함한 Object + * + */ + support(): object { + return _.merge(this.options, this.page.support(), this.order.support()); + } + + /** + * + * 조회시 필요한 조건을 추가 + * + * @param options 조회 조건 + * + */ + addOptions(options: object) { + this.options = _.cloneDeep(options); + } +} \ No newline at end of file diff --git a/server/src/controller/api/common/pagenation/strategy/default-page.ts b/server/src/controller/api/common/pagenation/strategy/default-page.ts new file mode 100644 index 00000000..7f286cb7 --- /dev/null +++ b/server/src/controller/api/common/pagenation/strategy/default-page.ts @@ -0,0 +1,33 @@ +import {Page} from "./page"; +import {Purifier} from "./util/purifier"; + +/** + * + * Pagination 기본 전략 + * page, size 기준으로 특정 구간의 데이터를 조회 + * + */ +export class DefaultPage implements Page { + private static readonly DEFAULT_PAGE = 1; + private static readonly DEFAULT_SIZE = 15; + private static readonly MINIMUM_PAGE = 1; + private static readonly MINIMUM_SIZE = 1; + private readonly page: number; + private readonly size: number; + + constructor(page?: number, size?: number) { + this.page = Purifier.refine(page, DefaultPage.MINIMUM_PAGE, DefaultPage.DEFAULT_PAGE); + this.size = Purifier.refine(size, DefaultPage.MINIMUM_SIZE, DefaultPage.DEFAULT_SIZE); + } + + private calculateSkip(page: number, size: number): number { + return (page - 1) * size; + } + + support(): object { + return { + skip: this.calculateSkip(this.page, this.size), + take: this.size + }; + } +} \ No newline at end of file diff --git a/server/src/controller/api/common/pagenation/strategy/id-page.ts b/server/src/controller/api/common/pagenation/strategy/id-page.ts new file mode 100644 index 00000000..689f4413 --- /dev/null +++ b/server/src/controller/api/common/pagenation/strategy/id-page.ts @@ -0,0 +1,34 @@ +import {Page} from "./page"; +import {Purifier} from "./util/purifier"; +import {LessThan} from "typeorm"; + +/** + * + * ID 기준으로 Pagination 지원하는 전략 + * + */ +export class IdPage implements Page { + private static readonly DEFAULT_ID = 1; + private static readonly DEFAULT_SIZE = 15; + private static readonly MINIMUM_ID = 1; + private static readonly MINIMUM_SIZE = 1; + private readonly id: number; + private readonly size: number; + + constructor(id: number, size: number) { + this.id = Purifier.refine(id, IdPage.MINIMUM_ID, IdPage.DEFAULT_ID); + this.size = Purifier.refine(size, IdPage.MINIMUM_SIZE, IdPage.DEFAULT_SIZE); + } + + /** + * + * ID 보다 작은 데이터 기준으로 take 만큼 조회 + * + */ + support(): object { + return { + take: this.size, + where: {id: LessThan(this.id)} + }; + } +} \ No newline at end of file diff --git a/server/src/controller/api/common/pagenation/strategy/page.ts b/server/src/controller/api/common/pagenation/strategy/page.ts new file mode 100644 index 00000000..7a29bfd3 --- /dev/null +++ b/server/src/controller/api/common/pagenation/strategy/page.ts @@ -0,0 +1,8 @@ +/** + * + * Page 정보를 제공하기 위한 전략 인터페이스 + * + */ +export interface Page { + support(): object; +} \ No newline at end of file diff --git a/server/src/controller/api/common/pagenation/strategy/util/purifier.ts b/server/src/controller/api/common/pagenation/strategy/util/purifier.ts new file mode 100644 index 00000000..034f71ab --- /dev/null +++ b/server/src/controller/api/common/pagenation/strategy/util/purifier.ts @@ -0,0 +1,13 @@ +export class Purifier { + static isSuitable(target: number, comparer: number): boolean { + return !target || target < comparer; + } + + static refine(target: number, comparer: number, substitution: number): number { + if(this.isSuitable(target, comparer)) { + return substitution; + } + + return target; + } +} \ No newline at end of file diff --git a/server/src/controller/api/common/paginator.ts b/server/src/controller/api/common/paginator.ts deleted file mode 100644 index 949767a4..00000000 --- a/server/src/controller/api/common/paginator.ts +++ /dev/null @@ -1,61 +0,0 @@ -import {Order} from "./order"; - -/** - * - * TypeORM 의 Pagination 기능을 지원하는 객체 - * - * */ -export class Paginator { - private static readonly DEFAULT_PAGE = 0; - private static readonly DEFAULT_SIZE = 15; - - private readonly page: number; - private readonly size: number; - private readonly order: Order; - - constructor({page, size}) { - this.page = page || Paginator.DEFAULT_PAGE; - this.size = size || Paginator.DEFAULT_SIZE; - this.order = new Order(); - } - - /** - * - * 특정 칼럼에 대한 정렬 조건을 Order 객체에 저장 - * - * @param key Column - * @param value SORT (ex, ASC/DESC) - * @return itself(Pageable) - * - * */ - addOrder(key: string, value: string): Paginator { - this.order.add(key, value); - return this; - } - - /** - * - * page, size, Order 기반으로 TypeORM 옵션 지원 - * - * @return TypeORM 옵션인 page, size, order 포함한 Object - * - * */ - support(): object { - return { - skip: this.page, - take: this.size, - ...this.order.support() - }; - } - - /** - * - * page, size 대한 Default 값 제공 - * - * @return [default page, default, size] - * - * */ - static getDefaultValues(): Array { - return [Paginator.DEFAULT_PAGE, Paginator.DEFAULT_SIZE]; - } -} \ No newline at end of file diff --git a/server/src/controller/api/common/status-code.ts b/server/src/controller/api/common/status-code.ts deleted file mode 100644 index 4345ed3f..00000000 --- a/server/src/controller/api/common/status-code.ts +++ /dev/null @@ -1,9 +0,0 @@ -export const OK=200; - -export const CREATED=201; - -export const NOT_FOUND=404; - -export const CONFLICT=409; - -export const INTERNAL_SERVER_ERROR=500; \ No newline at end of file diff --git a/server/src/controller/api/common/token/profile-token.ts b/server/src/controller/api/common/token/profile-token.ts new file mode 100644 index 00000000..33334f36 --- /dev/null +++ b/server/src/controller/api/common/token/profile-token.ts @@ -0,0 +1,8 @@ +import {Token} from "./token"; +import {ProfileInfo} from "../../../../model/profile/profile-info"; + +export class ProfileToken extends Token { + parsePayloadBy(profileInfo: ProfileInfo): object { + return profileInfo.asObject(); + } +} diff --git a/server/src/controller/api/common/token/token.ts b/server/src/controller/api/common/token/token.ts new file mode 100644 index 00000000..0d3bd421 --- /dev/null +++ b/server/src/controller/api/common/token/token.ts @@ -0,0 +1,10 @@ +import jwt from "jsonwebtoken"; + +export abstract class Token { + public abstract parsePayloadBy(base: T): object; + + public tokenize(base: T): string { + const payload = this.parsePayloadBy(base); + return jwt.sign(payload, process.env.SECRET_KEY); + }; +} \ No newline at end of file diff --git a/server/src/controller/api/common/token/user-token.ts b/server/src/controller/api/common/token/user-token.ts new file mode 100644 index 00000000..25690179 --- /dev/null +++ b/server/src/controller/api/common/token/user-token.ts @@ -0,0 +1,13 @@ +import {Email} from "../../../../domain/vo/Email"; +import {User} from "../../../../domain/entity/User"; +import {Token} from "./token"; +import _ from "lodash"; + +export class UserToken extends Token { + private static readonly TOKEN_ITEMS = ["id", "name", "email"]; + + parsePayloadBy(user: User): object { + const intermediatePayload = _.pick(user, UserToken.TOKEN_ITEMS); + return _.update(intermediatePayload, "email", (email: Email) => email.asFormat()); + } +} \ No newline at end of file diff --git a/server/src/controller/api/invite-controller.ts b/server/src/controller/api/invite-controller.ts new file mode 100644 index 00000000..4faf3f75 --- /dev/null +++ b/server/src/controller/api/invite-controller.ts @@ -0,0 +1,84 @@ +import {NextFunction, Request, Response} from "express"; +import {ACCEPTED, CONFLICT, FORBIDDEN, OK, UNPROCESSABLE_ENTITY} from "http-status-codes"; +import {Inviter} from "../../model/invite/inviter"; +import {EmailNotifier} from "../../model/notifier/email-notifier"; +import {InviteNotifier} from "../../model/notifier/invite-notifier"; +import { + ALREADY_JOINED_SNUG, + FOUND_INVITATIONS, + INVALID_TICKET, + NOT_FOUND, + SUCCESS_INVITE, + SUCCESS_JOIN_SNUG, + SUCCESS_REJECT_INVITATION_SNUG +} from "./common/messages"; +import ResponseForm from "../../utils/response-form"; +import UrlInfo from "../../utils/url-info"; +import {Invitee} from "../../model/invite/invitee"; +import {Ticket} from "../../domain/vo/Ticket"; + +export const invite = async (request: Request, response: Response): Promise => { + const {snugId} = request.params; + const {emails} = request.body; + const inviter = new Inviter(new EmailNotifier(), new InviteNotifier()); + try { + const invitations = await inviter.invite(snugId, emails); + response.status(OK) + .json(ResponseForm.of(SUCCESS_INVITE, {invitations})); + } catch(error) { + response.status(UNPROCESSABLE_ENTITY) + .json(ResponseForm.of(NOT_FOUND,{link: UrlInfo.aboutHome(), invitations: []})); + } +}; + +export const findInvitations = async (request: Request, response: Response): Promise => { + const {userId} = request.params; + const invitee = new Invitee(); + const invitations = await invitee.findInvitations(userId); + response.status(OK) + .json(ResponseForm.of(FOUND_INVITATIONS, {invitations})); +}; + +export const verify = async (request: Request, response: Response, next: NextFunction): Promise => { + const {ticket} = request.params; + const {agree} = request.body; + const ticketModel = Ticket.from(ticket); + const invitee = new Invitee(); + try { + request["snug"] = await invitee.joinSnug(ticketModel, agree); + } catch(error) { + request["invite_snug"] = await invitee.findInvitationByTicket(ticketModel); + } finally { + next(); + } +}; + +export const redirectBySnug = (request: Request, response: Response): void => { + const snug = request["snug"] || request["invite_snug"]; + if(!!snug) { + return response.redirect(snug.link); + } + + response.redirect(UrlInfo.aboutHome()); +}; + +export const responseBySnug = (request: Request, response: Response): Response => { + const {agree} = request.body; + const snug = request["snug"]; + const inviteSnug = request["invite_snug"]; + if(!!snug) { + if(agree) { + return response.status(ACCEPTED) + .json(ResponseForm.of(SUCCESS_JOIN_SNUG, {snug: snug})); + } else { + return response.status(ACCEPTED) + .json(ResponseForm.of(SUCCESS_REJECT_INVITATION_SNUG, {snug: {link: UrlInfo.aboutHome()}})); + } + } else if(!!inviteSnug) { + return response.status(CONFLICT) + .json(ResponseForm.of(ALREADY_JOINED_SNUG, {snug: inviteSnug})); + } + + return response.status(FORBIDDEN) + .json(ResponseForm.of(INVALID_TICKET, {snug: {link: UrlInfo.aboutHome()}})); +}; \ No newline at end of file diff --git a/server/src/controller/api/participate-in-controller.ts b/server/src/controller/api/participate-in-controller.ts new file mode 100644 index 00000000..b8a8f340 --- /dev/null +++ b/server/src/controller/api/participate-in-controller.ts @@ -0,0 +1,19 @@ +import { ParticipateIn } from "./../../domain/entity/ParticipateIn"; +import { Profile } from "./../../domain/entity/Profile"; +import { Request, Response } from "express"; +import { OK, NOT_FOUND } from "http-status-codes"; +import ResponseForm from "../../utils/response-form"; +import { offerProfileTokenInfo } from "../../validator/identifier-validator"; + +export const getChannels = async (request: Request, response: Response) => { + try { + const profile: Profile = offerProfileTokenInfo(request); + const rooms = await ParticipateIn.find({ + where: { Participant: profile.id }, + relations: ["room"] + }); + response.status(OK).json(ResponseForm.of("", rooms)); + } catch (error) { + response.status(NOT_FOUND).json(ResponseForm.of(error.message)); + } +}; diff --git a/server/src/controller/api/post-controller.ts b/server/src/controller/api/post-controller.ts index a07cd7c4..99622e78 100644 --- a/server/src/controller/api/post-controller.ts +++ b/server/src/controller/api/post-controller.ts @@ -1,16 +1,19 @@ -import { Post } from "../../entity/Post"; +import { Post } from "../../domain/entity/Post"; import { Request, Response } from "express"; -import { Paginator } from "./common/paginator"; +import { Paginator } from "./common/pagenation/paginator"; import ResponseForm from "../../utils/response-form"; import { publishIO } from "../../socket/socket-manager"; -import { Profile } from "../../entity/Profile"; -import { CREATED, NOT_FOUND, OK } from "./common/status-code"; +import { Profile } from "../../domain/entity/Profile"; +import { CREATED, NOT_FOUND, OK } from "http-status-codes"; import { FOUND_CHANNEL, FOUND_POST_PROFILE, NOT_FOUND_PROFILE -} from "./common/error-message"; +} from "./common/messages"; import { PUBLISH_EVENT } from "../../socket/common/events/publish-type"; +import { Page } from "./common/pagenation/strategy/page"; +import { IdPage } from "./common/pagenation/strategy/id-page"; +import { DefaultPage } from "./common/pagenation/strategy/default-page"; /** * @@ -19,22 +22,41 @@ import { PUBLISH_EVENT } from "../../socket/common/events/publish-type"; * @param request * @param response * - * */ + */ export const create = async (request: Request, response: Response) => { const { profileId, contents, roomId } = request.body; console.log(request.body); try { const profile = await Profile.findOneOrFail(profileId); - const post = await Post.save({ contents, profile: profile, room: roomId } as Post); + const post = await Post.save({ + contents, + profile: profile, + room: roomId + } as Post); const responseForm = ResponseForm.of(FOUND_POST_PROFILE, post); - publishIO().emit(PUBLISH_EVENT.SEND_MESSAGE, responseForm); + publishIO() + .of("/snug") + .to(roomId) + .emit(PUBLISH_EVENT.SEND_MESSAGE, responseForm); return response.status(CREATED).json(responseForm); } catch (error) { return response.status(NOT_FOUND).json(ResponseForm.of(NOT_FOUND_PROFILE)); } }; +/** + * + * post id 존재 여부에 따라 페이징 전략 선택 + * + * @param postId + * @param size + * + */ +const choosePage = (postId: number, size: number): Page => { + return !!postId ? new IdPage(postId, size) : new DefaultPage(0, size); +}; + /** * * channel id 에 해당하는 posts 조회 @@ -42,14 +64,17 @@ export const create = async (request: Request, response: Response) => { * @param request * @param response * - * */ + */ export const findByChannelId = async (request: Request, response: Response) => { - const { id } = request.params; - const pageable = new Paginator(request.query) - .addOrder("id", request.query.order) - .support(); - const posts = await Post.findByChannelId(id, pageable); + const { channelId } = request.params; + const { postId, size, order } = request.query; + + const page: Page = choosePage(postId, size); + const paginator = new Paginator(page).addOrder("id", order); + + const cacheKey = Post.generateCacheKeyByPosts(channelId, postId || "default"); + const posts = await Post.findByChannelId(channelId, cacheKey, paginator); return response.status(OK).json( - ResponseForm.of(FOUND_CHANNEL, { posts: posts }) + ResponseForm.of(FOUND_CHANNEL, { posts: posts.reverse() }) ); }; diff --git a/server/src/controller/api/profile-controller.ts b/server/src/controller/api/profile-controller.ts new file mode 100644 index 00000000..b1e2c47f --- /dev/null +++ b/server/src/controller/api/profile-controller.ts @@ -0,0 +1,64 @@ +import { NextFunction, Request, Response } from "express"; +import { Profile } from "../../domain/entity/Profile"; +import { Profiler } from "../../model/profile/profiler"; +import ResponseForm from "../../utils/response-form"; +import { ACCEPTED, OK, UNAUTHORIZED } from "http-status-codes"; +import { offerTokenInfo, UserInfo } from "../../validator/identifier-validator"; +import { + INACCESSIBLE_PROFILE, + SUCCESS_FIND_PROFILE, + SUCCESS_UPDATE_PROFILE +} from "./common/messages"; +import { Token } from "./common/token/token"; +import { ProfileInfo } from "../../model/profile/profile-info"; +import { ProfileToken } from "./common/token/profile-token"; + +export const isAccessibleProfile = async ( + request: Request, + response: Response, + next: NextFunction +): Promise => { + const { profileId } = request.params; + const userInfo: UserInfo = offerTokenInfo(request); + const isAccessible = await Profile.hasProfileByUserId(profileId, userInfo.id); + if (isAccessible) { + return next(); + } + + response.status(UNAUTHORIZED).json(ResponseForm.of(INACCESSIBLE_PROFILE)); +}; + +export const update = async ( + request: Request, + response: Response +): Promise => { + const { profileId } = request.params; + const { name, status, thumbnail, phone, description } = request.body; + const profile = Profile.builder() + .addName(name) + .addPhone(phone) + .addStatus(status) + .addThumbnail(thumbnail) + .addDescription(description) + .build(); + + const profiler = new Profiler(); + const profileRevision = await profiler.update(profileId, profile); + const profileToken: Token = new ProfileToken(); + return response + .status(ACCEPTED) + .cookie("profile", profileToken.tokenize(profileRevision)) + .json(ResponseForm.of(SUCCESS_UPDATE_PROFILE, profileRevision)); +}; + +export const findById = async ( + request: Request, + response: Response +): Promise => { + const { profileId } = request.params; + const profiler = new Profiler(); + const profileModel = await profiler.findById(profileId); + return response + .status(OK) + .json(ResponseForm.of(SUCCESS_FIND_PROFILE, profileModel)); +}; diff --git a/server/src/controller/api/snug-controller.ts b/server/src/controller/api/snug-controller.ts new file mode 100644 index 00000000..6ac5eb3d --- /dev/null +++ b/server/src/controller/api/snug-controller.ts @@ -0,0 +1,88 @@ +import {getManager} from "typeorm"; +import {User} from "../../domain/entity/User"; +import {Snug} from "../../domain/entity/Snug"; +import {Profile, UserRole} from "../../domain/entity/Profile"; +import {Room} from "../../domain/entity/Room"; +import {ParticipateIn} from "../../domain/entity/ParticipateIn"; +import {NextFunction, Request, Response} from "express"; +import ResponseForm from "../../utils/response-form"; +import { OK, CREATED, INTERNAL_SERVER_ERROR } from "http-status-codes"; +import { offerTokenInfo, UserInfo } from "../../validator/identifier-validator"; +import { CREATED_SNUG, OK_SNUG } from "./common/messages"; + +/** + * client에서 보내온 메시지를 기반으로 snug를 DB에 저장 + * Snug, Profile, Room, ParticipateIn에 데이터 생성 + * @param request + * @param response + * + * */ +export const create = async (request: Request, response: Response, next: NextFunction) => { + const { name, description, thumbnail } = request.body; + const userInfo: UserInfo = offerTokenInfo(request); + + try { + await getManager().transaction(async transactionalEntityManager => { + /** + * 1. snug row 생성 + * 2. 전달된 userID를 통해 profile row를 저장 + * 3. 생성된 snug를 통해 room row 저장 + * 4. 생성된 profile과 room을 통해 particiapte in 저장 + */ + // 미들웨어에 user 객체가 존재 or db 조회 + const user: User = await transactionalEntityManager.findOne(User, {id:userInfo.id}); + + console.log(userInfo); + console.log(user); + + const snug: Snug = new Snug(); + snug.name = name; + snug.description = description; + snug.thumbnail = thumbnail; + const resultSnug = await transactionalEntityManager.save(snug); + + const profile: Profile = new Profile(); + profile.name = user.name; + profile.status = ""; + profile.role = UserRole.ADMIN; + profile.user = user; + profile.snug = resultSnug; + const resultProfile = await transactionalEntityManager.save(profile); + + // room 생성 + const room: Room = new Room(); + + room.title = "기본 채널"; + room.isPrivate = false; + room.isChannel = true; + room.snug = resultSnug; + room.creator = profile; + const resultRoom = await transactionalEntityManager.save(room); + + // participate + const particiapteIn: ParticipateIn = new ParticipateIn(resultProfile, resultRoom); + await transactionalEntityManager.save(particiapteIn); + + const responseForm = ResponseForm.of(CREATED_SNUG, resultSnug); + response.status(CREATED).json(responseForm); + }); + } catch (error) { + return response.status(INTERNAL_SERVER_ERROR).json(ResponseForm.of(error.messagenp)); + } +}; + +export const findByUserId = async (request: Request, response: Response, next: NextFunction) => { + try { + const userInfo: UserInfo = offerTokenInfo(request); + + const user: User = await User.findOne({where: {id: userInfo.id}}); + const profiles: Profile[] = await getManager().find(Profile ,{ where: { user: user.id }, relations: ["snug"] }); + const snugs: Snug[] = profiles.map((profile) => { + return profile.snug; + }); + + response.status(OK).json(ResponseForm.of(OK_SNUG, snugs)); + } catch(error) { + return response.status(INTERNAL_SERVER_ERROR).json(ResponseForm.of(error.messagenp)); + } +}; \ No newline at end of file diff --git a/server/src/controller/api/user-controller.ts b/server/src/controller/api/user-controller.ts new file mode 100644 index 00000000..0b2473f7 --- /dev/null +++ b/server/src/controller/api/user-controller.ts @@ -0,0 +1,46 @@ +import { User } from "../../domain/entity/User"; +import { Request, Response } from "express"; +import ResponseForm from "../../utils/response-form"; +import { CREATED, OK, NOT_FOUND } from "http-status-codes"; +import { + CREATE_USER_SUCCESSFULLY, + FOUND_EMAIL_USER, + NO_USER_WITH_EMAIL +} from "./common/messages"; +import { generateHashedPassword } from "../../utils/password/generate-password"; +import {Email} from "../../domain/vo/Email"; + +/** + * + * client에서 보내온 메시지를 기반으로 post를 DB에 저장 + * + * @param request + * @param response + * + * */ +export const create = async (request: Request, response: Response) => { + const { email, name, password } = request.body; + const hashedPassword = await generateHashedPassword(password); + const emailModel = Email.from(email); + const user = await User.save({ + email: emailModel, + name, + password: hashedPassword + } as User); + const responseForm = ResponseForm.of(CREATE_USER_SUCCESSFULLY, user); + return response.status(CREATED).json(responseForm); +}; + +export const findByEmail = async (request: Request, response: Response) => { + const email = request.params.email; + const emailModel = Email.from(email); + + try { + const user = await User.findOneOrFail({ email: emailModel }); + return response + .status(OK) + .json(ResponseForm.of(FOUND_EMAIL_USER, user)); + } catch (error) { + return response.status(NOT_FOUND).json(ResponseForm.of(NO_USER_WITH_EMAIL)); + } +}; diff --git a/server/src/controller/index-controller.ts b/server/src/controller/index-controller.ts new file mode 100644 index 00000000..a8cb1552 --- /dev/null +++ b/server/src/controller/index-controller.ts @@ -0,0 +1,5 @@ +import {Request, Response} from "express"; + +export const index = (request: Request, response: Response) => { + response.sendFile("/index.html"); +}; \ No newline at end of file diff --git a/server/src/entity/Base.ts b/server/src/domain/entity/Base.ts similarity index 100% rename from server/src/entity/Base.ts rename to server/src/domain/entity/Base.ts diff --git a/server/src/domain/entity/Invite.ts b/server/src/domain/entity/Invite.ts new file mode 100644 index 00000000..f0b6ee3d --- /dev/null +++ b/server/src/domain/entity/Invite.ts @@ -0,0 +1,68 @@ +import {Column, Entity, IsNull, JoinColumn, ManyToOne, PrimaryGeneratedColumn} from "typeorm"; +import {EmailContents} from "../../template/email-contents"; +import UrlInfo from "../../utils/url-info"; +import {Email} from "../vo/Email"; +import {Ticket} from "../vo/Ticket"; +import {Base} from "./Base"; +import {User} from "./User"; +import {Snug} from "./Snug"; + +@Entity() +export class Invite extends Base { + @PrimaryGeneratedColumn() + id: number; + + @Column(type=> Ticket) + ticket: Ticket; + + @Column(type=> Email) + email: Email; + + @Column({nullable: true}) + deletedAt: Date; + + @ManyToOne(type => User) + @JoinColumn({referencedColumnName: "id"}) + user: User; + + @ManyToOne(type => Snug, snug => snug.invitations, {eager: true}) + snug: Snug; + + constructor(user: User, snug: Snug) { + super(); + this.user = user; + this.snug = snug; + this.ticket = Ticket.generate(); + if(this.user) { + this.email = user.email; + } + } + + public isUnsignedUser(): boolean { + return !this.user.id; + } + + public provideContents(): string { + if(this.isUnsignedUser()) { + const registerLink = UrlInfo.aboutRegister(); + return EmailContents.getTemplateForRegister(this.snug.name, registerLink); + } else { + const verificationLink = UrlInfo.aboutVerification(this.ticket.getValue()); + return EmailContents.getTemplateForVerification(this.snug.name, verificationLink); + } + + } + + public static findWithUserByTicket(ticket: Ticket): Promise { + return Invite.findOneOrFail( {relations: ["user"], where: {ticket: ticket.asObject(), deletedAt: IsNull()}}); + } + + public static findByTicket(ticket: Ticket): Promise { + return Invite.findOne({where: {ticket: ticket.asObject()}}); + } + + public static deleteBy(invite: Invite): Promise { + invite.deletedAt = new Date(); + return Invite.save(invite); + } +} \ No newline at end of file diff --git a/server/src/entity/ParticipateIn.ts b/server/src/domain/entity/ParticipateIn.ts similarity index 66% rename from server/src/entity/ParticipateIn.ts rename to server/src/domain/entity/ParticipateIn.ts index 69ded7c1..4bfaebea 100644 --- a/server/src/entity/ParticipateIn.ts +++ b/server/src/domain/entity/ParticipateIn.ts @@ -1,6 +1,7 @@ import { BaseEntity, Entity, PrimaryGeneratedColumn, ManyToOne } from "typeorm"; import { Profile } from "./Profile"; import { Room } from "./Room"; +import _ from "lodash"; @Entity() export class ParticipateIn extends BaseEntity { @@ -12,4 +13,10 @@ export class ParticipateIn extends BaseEntity { @ManyToOne(type => Room) room: Room; + + constructor(participant: Profile, room: Room) { + super(); + this.participant = _.cloneDeep(participant); + this.room = _.cloneDeep(room); + } } diff --git a/server/src/domain/entity/Post.ts b/server/src/domain/entity/Post.ts new file mode 100644 index 00000000..2e49021c --- /dev/null +++ b/server/src/domain/entity/Post.ts @@ -0,0 +1,53 @@ +import { + Column, + Entity, + ManyToOne, + OneToMany, + PrimaryGeneratedColumn +} from "typeorm"; +import { Profile } from "./Profile"; +import { Room } from "./Room"; +import { Base } from "./Base"; +import { Paginator } from "../../controller/api/common/pagenation/paginator"; +import _ from "lodash"; + +@Entity() +export class Post extends Base { + @PrimaryGeneratedColumn() + id: number; + @Column({ nullable: true }) + contents: string; + @Column({ nullable: true }) + imgSrc: string; + @ManyToOne(type => Profile, { eager: true }) + profile: Profile; + @ManyToOne(type => Room) + room: Room; + @ManyToOne( + type => Post, + post => post.childCategories + ) + parentCategory: Post; + @OneToMany( + type => Post, + post => post.parentCategory + ) + childCategories: Post[]; + + static findByChannelId( + channelId: string, + cacheKey: string, + paginator: Paginator + ): Promise { + paginator.addOptions({ + where: { room: channelId }, + cache: { id: cacheKey } + }); + return this.find(paginator.support()); + } + + static generateCacheKeyByPosts(roomId: string, postId: string): string { + const separator = "-"; + return _.join(["room", roomId, "post", postId], separator); + } +} diff --git a/server/src/domain/entity/Profile.ts b/server/src/domain/entity/Profile.ts new file mode 100644 index 00000000..629f6a7f --- /dev/null +++ b/server/src/domain/entity/Profile.ts @@ -0,0 +1,171 @@ +import { + Column, + Entity, + JoinColumn, + ManyToOne, + PrimaryGeneratedColumn +} from "typeorm"; +import { Snug } from "./Snug"; +import { User } from "./User"; +import { Base } from "./Base"; + +export enum UserRole { + ADMIN = "admin", + MEMBER = "member" +} + +@Entity() +export class Profile extends Base { + @PrimaryGeneratedColumn() + id: number; + @Column({ length: 64 }) + name: string; + @Column({ nullable: true, length: 128 }) + status: string; + @Column({ + nullable: true, + length: 256, + default: "/image/default-thumbnail.jpeg" + }) + thumbnail: string; + @Column({ nullable: true, length: 512 }) + description: string; + @Column({ nullable: true }) + phone: string; + @Column({ + type: "enum", + enum: UserRole, + default: UserRole.MEMBER + }) + role: UserRole; + @ManyToOne(type => Snug) + snug: Snug; + @ManyToOne(type => User) + @JoinColumn({ referencedColumnName: "id" }) + user: User; + + static async hasProfileByUserId( + profileId: string, + userId: number + ): Promise { + const user = User.create({ id: userId }); + const profile = await Profile.findOne({ + where: { id: profileId, user: user } + }); + return profile && profile.hasId(); + } + + static findById(profileId: string): Promise { + return Profile.findOne(profileId, { relations: ["user", "snug"] }); + } + + static findOneByUserIdAndSnugId( + userId: string, + snugId: string + ): Promise { + return Profile.findOneOrFail({ + where: { user: userId, snug: snugId }, + relations: ["user", "snug"] + }); + } + + static build(builder: Builder): Profile { + const profile = new Profile(); + profile.name = builder.getName(); + profile.status = builder.getStatus(); + profile.thumbnail = builder.getThumbnail(); + profile.description = builder.getDescription(); + profile.phone = builder.getPhone(); + profile.role = builder.getRole(); + profile.snug = builder.getSnug(); + profile.user = builder.getUser(); + return profile; + } + + static builder(snug?: Snug, user?: User): Builder { + return new Builder(snug, user); + } +} + +class Builder { + private readonly snug: Snug; + private readonly user: User; + private name: string; + private status: string; + private thumbnail: string; + private description: string; + private phone: string; + private role: UserRole; + + constructor(snug: Snug, user: User) { + this.snug = snug; + this.user = user; + this.name = user && user.name; + } + + build(): Profile { + return Profile.build(this); + } + + addName(name: string): Builder { + this.name = name; + return this; + } + + addStatus(status: string): Builder { + this.status = status; + return this; + } + + addThumbnail(thumbnail: string): Builder { + this.thumbnail = thumbnail; + return this; + } + + addDescription(description: string): Builder { + this.description = description; + return this; + } + + addPhone(phone: string): Builder { + this.phone = phone; + return this; + } + + addRole(role: UserRole): Builder { + this.role = role; + return this; + } + + getName(): string { + return this.name; + } + + getStatus(): string { + return this.status; + } + + getThumbnail(): string { + return this.thumbnail; + } + + getDescription(): string { + return this.description; + } + + getPhone(): string { + return this.phone; + } + + getRole(): UserRole { + return this.role; + } + + getSnug(): Snug { + return this.snug; + } + + getUser(): User { + return this.user; + } +} diff --git a/server/src/entity/Room.ts b/server/src/domain/entity/Room.ts similarity index 66% rename from server/src/entity/Room.ts rename to server/src/domain/entity/Room.ts index a1757738..fdc9ff60 100644 --- a/server/src/entity/Room.ts +++ b/server/src/domain/entity/Room.ts @@ -2,6 +2,7 @@ import {Column, Entity, ManyToOne, PrimaryGeneratedColumn} from "typeorm"; import {Profile} from "./Profile"; import {Snug} from "./Snug"; import {Base} from "./Base"; +import {Order} from "../../controller/api/common/order"; @Entity() export class Room extends Base { @@ -29,4 +30,11 @@ export class Room extends Base { static findByTitle(title: string): Promise { return Room.findOne({where: {title: title}}); } + + static findDefaultChannelBySnug(snug: Snug): Promise { + const order = new Order() + .add("id", "ASC") + .support(); + return Room.findOneOrFail({where: {isPrivate: false, isChannel: true, snug: snug}, ...order}); + } } \ No newline at end of file diff --git a/server/src/domain/entity/Snug.ts b/server/src/domain/entity/Snug.ts new file mode 100644 index 00000000..d9891ca3 --- /dev/null +++ b/server/src/domain/entity/Snug.ts @@ -0,0 +1,21 @@ +import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm"; +import { Base } from "./Base"; +import {Invite} from "./Invite"; + +@Entity() +export class Snug extends Base { + @PrimaryGeneratedColumn() + id: number; + + @Column() + name: string; + + @Column({ nullable: true }) + thumbnail: string; + + @Column({ nullable: true }) + description: string; + + @OneToMany(type => Invite, invite => invite.snug) + invitations: Invite[]; +} diff --git a/server/src/domain/entity/User.ts b/server/src/domain/entity/User.ts new file mode 100644 index 00000000..2ca73a6e --- /dev/null +++ b/server/src/domain/entity/User.ts @@ -0,0 +1,37 @@ +import {Column, Entity, PrimaryGeneratedColumn} from "typeorm"; +import {Base} from "./Base"; +import {Email} from "../vo/Email"; +import _ from "lodash"; + +@Entity() +export class User extends Base { + @PrimaryGeneratedColumn() + id: number; + + @Column(type=> Email) + email: Email; + + @Column() + name: string; + + @Column() + password: string; + + constructor(email?: Email) { + super(); + this.email = email; + } + + static findByEmails(emails: string[]): Promise { + const emailOptions = emails + .map(email => Email.from(email)) + .map(email => email.asObject()) + .map(email => {return {email};}); + + return User.find({where: emailOptions}); + } + + hasSameEmail(email: string): boolean { + return _.isEqual(this.email.asFormat(), email); + } +} diff --git a/server/src/domain/vo/Email.ts b/server/src/domain/vo/Email.ts new file mode 100644 index 00000000..4bdd246f --- /dev/null +++ b/server/src/domain/vo/Email.ts @@ -0,0 +1,57 @@ +import {Column, Index} from "typeorm"; +import {checkInvalidEmail} from "../../validator/email-validator"; +import InvalidEmailException from "../../utils/exception/InvalidEmailException"; +import {Transporter} from "nodemailer"; +import TransferEmailException from "../../utils/exception/TransferEmailException"; + +@Index("email_uniq_index", ["localPart", "domain"], { unique: true }) +export class Email { + @Column({length: 64}) + private readonly localPart: string; + @Column({length: 255}) + private readonly domain: string; + private static readonly DELIMITER = "@"; + private contents: string; + + private constructor(localPart: string, domain: string, contents: string) { + this.localPart = localPart; + this.domain = domain; + this.contents = contents; + } + + static from(email: string, contents?: string): Email { + if (checkInvalidEmail(email)) { + throw new InvalidEmailException("유효하지 않은 이메일 형식입니다"); + } + + const [localPart, domain] = Email.tokenize(email); + return new Email(localPart, domain, contents || ""); + } + + private static tokenize(email: string): string[] { + return email.split(Email.DELIMITER); + } + + public sendTo(transporter: Transporter, sender: string): Promise { + return transporter.sendMail({ + from: sender, + to: this.asFormat(), + subject: "✔ Snug confirmation link", + html: this.contents + }).catch(this.handleTransferEmailError); + } + + private handleTransferEmailError(error: Error): void { + if (error) { + throw new TransferEmailException(error.message); + } + } + + asFormat(): string { + return this.localPart + Email.DELIMITER + this.domain; + } + + asObject(): object { + return {localPart: this.localPart, domain: this.domain}; + } +} \ No newline at end of file diff --git a/server/src/domain/vo/Ticket.ts b/server/src/domain/vo/Ticket.ts new file mode 100644 index 00000000..98bfae71 --- /dev/null +++ b/server/src/domain/vo/Ticket.ts @@ -0,0 +1,32 @@ +import {Column, Index} from "typeorm"; + +@Index("ticket_uniq_index", ["id"], { unique: true }) +export class Ticket { + @Column() + private readonly id: string; + + private constructor(id: string) { + this.id = id; + } + + static generate(): Ticket { + return new Ticket(Ticket.rand() + Ticket.rand()); + }; + + static from(id: string): Ticket { + return new Ticket(id); + }; + + // https://stackoverflow.com/questions/8532406/create-a-random-token-in-javascript-based-on-user-details + static rand(): string { + return Math.random().toString(36).substr(2); + }; + + asObject(): object { + return {id: this.id}; + }; + + getValue(): string { + return this.id; + } +} \ No newline at end of file diff --git a/server/src/entity/Post.ts b/server/src/entity/Post.ts deleted file mode 100644 index ed4acccb..00000000 --- a/server/src/entity/Post.ts +++ /dev/null @@ -1,32 +0,0 @@ -import {Column, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn} from "typeorm"; -import {Profile} from "./Profile"; -import {Room} from "./Room"; -import {Base} from "./Base"; - -@Entity() -export class Post extends Base { - @PrimaryGeneratedColumn() - id: number; - @Column({nullable: true}) - contents: string; - @Column({nullable: true}) - imgSrc: string; - @ManyToOne(type => Profile, {eager: true}) - profile: Profile; - @ManyToOne(type => Room) - room: Room; - @ManyToOne( - type => Post, - post => post.childCategories - ) - parentCategory: Post; - @OneToMany( - type => Post, - post => post.parentCategory - ) - childCategories: Post[]; - - static findByChannelId(id: string, pageable: object): Promise { - return this.find({where: {room: id}, ...pageable}); - } -} \ No newline at end of file diff --git a/server/src/entity/Profile.ts b/server/src/entity/Profile.ts deleted file mode 100644 index 20b7f47d..00000000 --- a/server/src/entity/Profile.ts +++ /dev/null @@ -1,36 +0,0 @@ -import {Column, Entity, ManyToOne, PrimaryGeneratedColumn} from "typeorm"; -import {Snug} from "./Snug"; -import {User} from "./User"; -import {Base} from "./Base"; - -export type UserRoleType = "admin" | "participant"; - -@Entity() -export class Profile extends Base { - @PrimaryGeneratedColumn() - id: number; - - @Column() - name: string; - - @Column() - status: string; - - @Column({ nullable: true }) - thumbnail: string; - - @Column({ nullable: true }) - description: string; - - @Column({ - type: "enum", - enum: ["admin", "member"] - }) - role: UserRoleType; - - @ManyToOne(type => Snug) - snug: Snug; - - @ManyToOne(type => User) - user: User; -} \ No newline at end of file diff --git a/server/src/entity/Snug.ts b/server/src/entity/Snug.ts deleted file mode 100644 index a4612153..00000000 --- a/server/src/entity/Snug.ts +++ /dev/null @@ -1,17 +0,0 @@ -import {Column, Entity, PrimaryGeneratedColumn} from "typeorm"; -import {Base} from "./Base"; - -@Entity() -export class Snug extends Base { - @PrimaryGeneratedColumn() - id: number; - - @Column() - name: string; - - @Column({ nullable: true }) - thumbnail: boolean; - - @Column({ nullable: true }) - description: boolean; -} diff --git a/server/src/entity/User.ts b/server/src/entity/User.ts deleted file mode 100644 index e915b401..00000000 --- a/server/src/entity/User.ts +++ /dev/null @@ -1,14 +0,0 @@ -import {Column, Entity, PrimaryGeneratedColumn} from "typeorm"; -import {Base} from "./Base"; - -@Entity() -export class User extends Base { - @PrimaryGeneratedColumn() - id: number; - - @Column() - email: string; - - @Column() - password: string; -} diff --git a/server/src/mail/mail-manager.ts b/server/src/mail/mail-manager.ts new file mode 100644 index 00000000..fa162a4b --- /dev/null +++ b/server/src/mail/mail-manager.ts @@ -0,0 +1,68 @@ +import nodemailer, {Transporter} from "nodemailer"; +import {isNotEmpty} from "../utils/array-helper"; +import {Email} from "../domain/vo/Email"; +import _ from "lodash"; + +export class MailManager { + private static readonly MAX_TRY_COUNT = 5; + private static readonly FIRST_TRY_COUNT = 0; + private static readonly IDLE_EVENT = "idle"; + private readonly transporter; + private static manager: MailManager; + + constructor() { + this.transporter = this.setUp(); + this.subscribes(); + } + + setUp(): Transporter { + return nodemailer.createTransport({ + pool: true, + maxConnections: parseInt(process.env.MAIL_POOL_SIZE!), + host: process.env.MAIL_HOST!, + port: parseInt(process.env.MAIL_PORT!), + secure: !!process.env.MAIL_SECURE!, + auth: { + user: process.env.MAIL_ADMIN!, + pass: process.env.MAIL_PASSWORD! + } + }); + } + + private subscribes(): void { + const sender = process.env.MIAL_SENDER!; + this.transporter.on(MailManager.IDLE_EVENT, (emails: Email[]) => this.handleIdleEvent(sender, emails)); + } + + private handleIdleEvent(sender: string, emails: Email[]): void { + const cloneEmails = _.cloneDeep(emails); + while (this.transporter.isIdle() && isNotEmpty(cloneEmails)) { + const email = cloneEmails.shift(); + this.send(sender, email, MailManager.FIRST_TRY_COUNT); + } + } + + private async send(sender: string, email: Email, tryCount: number): Promise { + if (tryCount < MailManager.MAX_TRY_COUNT) { + try { + await email.sendTo(this.transporter, sender); + console.log(`${email.asFormat()} : ${tryCount} 시도 전송 성공`); + } catch (error) { + console.error(`${email.asFormat()} : ${tryCount} 시도 전송 실패`); + this.send(sender, email, tryCount + 1); + } + } + } + + public static initializeMailManger(): MailManager { + return MailManager.manager = new MailManager(); + } + + public static publish(emails: Email[]): boolean { + const cloneEmails = _.cloneDeep(emails); + return MailManager.manager.transporter.emit(MailManager.IDLE_EVENT, cloneEmails); + } +} + +export const initializeMailManger = MailManager.initializeMailManger; +export const publish = MailManager.publish; \ No newline at end of file diff --git a/server/src/middleware/errorHandler.ts b/server/src/middleware/errorHandler.ts index 1308f9bb..d938f5cf 100644 --- a/server/src/middleware/errorHandler.ts +++ b/server/src/middleware/errorHandler.ts @@ -1,21 +1,30 @@ -import {Router ,Request, Response, NextFunction } from "express"; -import HttpException from "../util/HttpException"; +import { Request, Response, NextFunction } from "express"; +import HttpException from "../utils/exception/HttpException"; +import ResponseForm from "../utils/response-form"; +import logger from "../utils/logger"; -const router = Router(); - -router.use((request: Request, response: Response, next: NextFunction) => { +export function notFoundHandler( + request: Request, + response: Response, + next: NextFunction +) { const notFoundError = new HttpException("not found url request", 404); + logger.error(notFoundError.message); next(notFoundError); -}); +} -router.use((error: Error, request: Request, response: Response, next: NextFunction) => { +export function errorResopnseHandler( + error: Error, + request: Request, + response: Response, + next: NextFunction +) { const status = (error as HttpException).status || 500; - const message = request.app.get("env") === "production" ? error.name : error.message || "Something went wrong"; - response.status(status) - .send({ - message, - payload: {}, - }); -}); + const message = + request.app.get("env") === "production" + ? error.name + : error.message || "Something went wrong"; -export default router; + logger.error(error.message); + response.status(status).json(ResponseForm.of(message)); +} diff --git a/server/src/middleware/validator.ts b/server/src/middleware/validator.ts new file mode 100644 index 00000000..46050780 --- /dev/null +++ b/server/src/middleware/validator.ts @@ -0,0 +1,70 @@ +import { Response, Request, NextFunction } from "express"; +import ResponseForm from "../utils/response-form"; +import {NO_USER_WITH_EMAIL, UNSUPPORTED_EMAIL} from "../controller/api/common/messages"; +import _ from "lodash"; + +import { + hasNotEveryNumber, + hasNotValue, + isOutOfRange +} from "../validator/identifier-validator"; +import { + validateEmail, + validatePasswordLength +} from "../validator/email-validator"; +import UrlInfo from "../utils/url-info"; +import {BAD_REQUEST, NOT_FOUND} from "http-status-codes"; + +/** + * + * request path variable 인 id 대한 유효성 검사 + * 유효한 경우, next() 메소드가 err 인자 없이 호출되고 + * 유효하지 않은 경우, next(err) 메소드가 err 인자를 가지고 호출 + * + * @param request express Request + * @param response express Response + * @param next express Next + * @param id + * + * */ +export const isNumeric = ( + request: Request, + response: Response, + next: NextFunction, + id: string +) => { + if (hasNotValue(id) || hasNotEveryNumber(id) || isOutOfRange(id)) { + return next("Invalid id format. Must be an Number"); + } + + next(); +}; + +export const isValidUserForm = ( + request: Request, + response: Response, + next: NextFunction +) => { + if ( + validateEmail(request.body.email) && + validatePasswordLength(request.body.password) + ) { + return next(); + } + + return response.status(NOT_FOUND).json(ResponseForm.of(NO_USER_WITH_EMAIL)); +}; + +export const isValidInviteForm = ( + request: Request, + response: Response, + next: NextFunction +) => { + + const {emails} = request.body; + if (_.every(emails, validateEmail)) { + return next(); + } + + return response.status(BAD_REQUEST).json(ResponseForm.of(UNSUPPORTED_EMAIL, {link: UrlInfo.aboutHome()})); +}; diff --git a/server/src/migration/1575357161313-ALTER-USERCOLUMN.ts b/server/src/migration/1575357161313-ALTER-USERCOLUMN.ts new file mode 100644 index 00000000..5dbc2b2f --- /dev/null +++ b/server/src/migration/1575357161313-ALTER-USERCOLUMN.ts @@ -0,0 +1,18 @@ +import {MigrationInterface, QueryRunner} from "typeorm"; + +export class ALTERUSERCOLUMN1575357161313 implements MigrationInterface { + name = 'ALTERUSERCOLUMN1575357161313' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query("ALTER TABLE `user` ADD `name` varchar(255) NOT NULL", undefined); + await queryRunner.query("ALTER TABLE `snug` DROP COLUMN `thumbnail`", undefined); + await queryRunner.query("ALTER TABLE `snug` ADD `thumbnail` varchar(255) NULL", undefined); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query("ALTER TABLE `snug` DROP COLUMN `thumbnail`", undefined); + await queryRunner.query("ALTER TABLE `snug` ADD `thumbnail` tinyint NULL", undefined); + await queryRunner.query("ALTER TABLE `user` DROP COLUMN `name`", undefined); + } + +} diff --git a/server/src/migration/1575362426119-ALTER-USEREMAIL.ts b/server/src/migration/1575362426119-ALTER-USEREMAIL.ts new file mode 100644 index 00000000..acf5d84a --- /dev/null +++ b/server/src/migration/1575362426119-ALTER-USEREMAIL.ts @@ -0,0 +1,14 @@ +import {MigrationInterface, QueryRunner} from "typeorm"; + +export class ALTERUSEREMAIL1575362426119 implements MigrationInterface { + name = 'ALTERUSEREMAIL1575362426119' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query("ALTER TABLE `user` ADD UNIQUE INDEX `IDX_e12875dfb3b1d92d7d7c5377e2` (`email`)", undefined); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query("ALTER TABLE `user` DROP INDEX `IDX_e12875dfb3b1d92d7d7c5377e2`", undefined); + } + +} diff --git a/server/src/migration/1575540485123-ADD-INVITE.ts b/server/src/migration/1575540485123-ADD-INVITE.ts new file mode 100644 index 00000000..3e67b33a --- /dev/null +++ b/server/src/migration/1575540485123-ADD-INVITE.ts @@ -0,0 +1,35 @@ +import {MigrationInterface, QueryRunner} from "typeorm"; + +export class ADDINVITE1575540485123 implements MigrationInterface { + name = "ADDINVITE1575540485123"; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query("ALTER TABLE `room` DROP FOREIGN KEY `FK_86e40e0afb08286884be0e6f38c`", undefined); + await queryRunner.query("ALTER TABLE `participate_in` DROP FOREIGN KEY `FK_d914b8226336ece30658108e80e`", undefined); + await queryRunner.query("ALTER TABLE `room` CHANGE `creator` `creatorId` int NULL", undefined); + await queryRunner.query("ALTER TABLE `participate_in` CHANGE `participant` `participantId` int NULL", undefined); + await queryRunner.query("CREATE TABLE `invite` (`createdAt` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `updatedAt` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `id` int NOT NULL AUTO_INCREMENT, `ticket` varchar(36) NOT NULL, `userId` int NULL, `snugId` int NULL, `emailLocalpart` varchar(64) NOT NULL, `emailDomain` varchar(255) NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB", undefined); + await queryRunner.query("ALTER TABLE `user` DROP COLUMN `email`", undefined); + await queryRunner.query("ALTER TABLE `user` ADD `emailLocalpart` varchar(64) NOT NULL", undefined); + await queryRunner.query("ALTER TABLE `user` ADD `emailDomain` varchar(255) NOT NULL", undefined); + await queryRunner.query("ALTER TABLE `invite` ADD CONSTRAINT `FK_91bfeec7a9574f458e5b592472d` FOREIGN KEY (`userId`) REFERENCES `user`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION", undefined); + await queryRunner.query("ALTER TABLE `invite` ADD CONSTRAINT `FK_e506ff62d7f2a270bd7803b04c5` FOREIGN KEY (`snugId`) REFERENCES `snug`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION", undefined); + await queryRunner.query("ALTER TABLE `room` ADD CONSTRAINT `FK_86e40e0afb08286884be0e6f38b` FOREIGN KEY (`creatorId`) REFERENCES `profile`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION", undefined); + await queryRunner.query("ALTER TABLE `participate_in` ADD CONSTRAINT `FK_d914b8226336ece30658108e80d` FOREIGN KEY (`participantId`) REFERENCES `profile`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION", undefined); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query("ALTER TABLE `participate_in` DROP FOREIGN KEY `FK_d914b8226336ece30658108e80d`", undefined); + await queryRunner.query("ALTER TABLE `room` DROP FOREIGN KEY `FK_86e40e0afb08286884be0e6f38b`", undefined); + await queryRunner.query("ALTER TABLE `invite` DROP FOREIGN KEY `FK_e506ff62d7f2a270bd7803b04c5`", undefined); + await queryRunner.query("ALTER TABLE `invite` DROP FOREIGN KEY `FK_91bfeec7a9574f458e5b592472d`", undefined); + await queryRunner.query("ALTER TABLE `user` DROP COLUMN `emailDomain`", undefined); + await queryRunner.query("ALTER TABLE `user` DROP COLUMN `emailLocalpart`", undefined); + await queryRunner.query("ALTER TABLE `user` ADD `email` varchar(255) NOT NULL", undefined); + await queryRunner.query("DROP TABLE `invite`", undefined); + await queryRunner.query("ALTER TABLE `participate_in` CHANGE `participantId` `participant` int NULL", undefined); + await queryRunner.query("ALTER TABLE `room` CHANGE `creatorId` `creator` int NULL", undefined); + await queryRunner.query("ALTER TABLE `participate_in` ADD CONSTRAINT `FK_d914b8226336ece30658108e80e` FOREIGN KEY (`participant`) REFERENCES `profile`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION", undefined); + await queryRunner.query("ALTER TABLE `room` ADD CONSTRAINT `FK_86e40e0afb08286884be0e6f38c` FOREIGN KEY (`creator`) REFERENCES `profile`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION", undefined); + } +} diff --git a/server/src/migration/1575542819077-CHANGE-EMAIL-AS-COMPOSITE-KEY.ts b/server/src/migration/1575542819077-CHANGE-EMAIL-AS-COMPOSITE-KEY.ts new file mode 100644 index 00000000..c0191a40 --- /dev/null +++ b/server/src/migration/1575542819077-CHANGE-EMAIL-AS-COMPOSITE-KEY.ts @@ -0,0 +1,52 @@ +import {MigrationInterface, QueryRunner} from "typeorm"; + +export class CHANGEEMAILASCOMPOSITEKEY1575542819077 implements MigrationInterface { + name = 'CHANGEEMAILASCOMPOSITEKEY1575542819077' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query("ALTER TABLE `invite` DROP FOREIGN KEY `FK_91bfeec7a9574f458e5b592472d`", undefined); + await queryRunner.query("ALTER TABLE `profile` DROP FOREIGN KEY `FK_a24972ebd73b106250713dcddd9`", undefined); + await queryRunner.query("ALTER TABLE `invite` ADD `userLocalPart` varchar(64) NULL", undefined); + await queryRunner.query("ALTER TABLE `invite` ADD `userDomain` varchar(255) NULL", undefined); + await queryRunner.query("ALTER TABLE `profile` ADD `userLocalPart` varchar(64) NULL", undefined); + await queryRunner.query("ALTER TABLE `profile` ADD `userDomain` varchar(255) NULL", undefined); + await queryRunner.query("ALTER TABLE `user` CHANGE `id` `id` int NOT NULL", undefined); + await queryRunner.query("ALTER TABLE `user` DROP PRIMARY KEY", undefined); + await queryRunner.query("ALTER TABLE `user` ADD PRIMARY KEY (`id`, `emailLocalpart`, `emailDomain`)", undefined); + await queryRunner.query("ALTER TABLE `user` CHANGE `id` `id` int NOT NULL AUTO_INCREMENT", undefined); + await queryRunner.query("ALTER TABLE `invite` CHANGE `id` `id` int NOT NULL", undefined); + await queryRunner.query("ALTER TABLE `invite` DROP PRIMARY KEY", undefined); + await queryRunner.query("ALTER TABLE `invite` ADD PRIMARY KEY (`id`, `emailLocalpart`, `emailDomain`)", undefined); + await queryRunner.query("ALTER TABLE `invite` CHANGE `id` `id` int NOT NULL AUTO_INCREMENT", undefined); + await queryRunner.query("ALTER TABLE `snug` DROP COLUMN `thumbnail`", undefined); + await queryRunner.query("ALTER TABLE `snug` ADD `thumbnail` varchar(255) NULL", undefined); + await queryRunner.query("ALTER TABLE `snug` DROP COLUMN `description`", undefined); + await queryRunner.query("ALTER TABLE `snug` ADD `description` varchar(255) NULL", undefined); + await queryRunner.query("ALTER TABLE `invite` ADD CONSTRAINT `FK_9baa86a15b26d03b384e35bc290` FOREIGN KEY (`userId`, `userLocalPart`, `userDomain`) REFERENCES `user`(`id`,`emailLocalpart`,`emailDomain`) ON DELETE NO ACTION ON UPDATE NO ACTION", undefined); + await queryRunner.query("ALTER TABLE `profile` ADD CONSTRAINT `FK_56adaed4f38934440c8a88cd50b` FOREIGN KEY (`userId`, `userLocalPart`, `userDomain`) REFERENCES `user`(`id`,`emailLocalpart`,`emailDomain`) ON DELETE NO ACTION ON UPDATE NO ACTION", undefined); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query("ALTER TABLE `profile` DROP FOREIGN KEY `FK_56adaed4f38934440c8a88cd50b`", undefined); + await queryRunner.query("ALTER TABLE `invite` DROP FOREIGN KEY `FK_9baa86a15b26d03b384e35bc290`", undefined); + await queryRunner.query("ALTER TABLE `snug` DROP COLUMN `description`", undefined); + await queryRunner.query("ALTER TABLE `snug` ADD `description` tinyint NULL", undefined); + await queryRunner.query("ALTER TABLE `snug` DROP COLUMN `thumbnail`", undefined); + await queryRunner.query("ALTER TABLE `snug` ADD `thumbnail` tinyint NULL", undefined); + await queryRunner.query("ALTER TABLE `invite` CHANGE `id` `id` int NOT NULL", undefined); + await queryRunner.query("ALTER TABLE `invite` DROP PRIMARY KEY", undefined); + await queryRunner.query("ALTER TABLE `invite` ADD PRIMARY KEY (`id`)", undefined); + await queryRunner.query("ALTER TABLE `invite` CHANGE `id` `id` int NOT NULL AUTO_INCREMENT", undefined); + await queryRunner.query("ALTER TABLE `user` CHANGE `id` `id` int NOT NULL", undefined); + await queryRunner.query("ALTER TABLE `user` DROP PRIMARY KEY", undefined); + await queryRunner.query("ALTER TABLE `user` ADD PRIMARY KEY (`id`)", undefined); + await queryRunner.query("ALTER TABLE `user` CHANGE `id` `id` int NOT NULL AUTO_INCREMENT", undefined); + await queryRunner.query("ALTER TABLE `profile` DROP COLUMN `userDomain`", undefined); + await queryRunner.query("ALTER TABLE `profile` DROP COLUMN `userLocalPart`", undefined); + await queryRunner.query("ALTER TABLE `invite` DROP COLUMN `userDomain`", undefined); + await queryRunner.query("ALTER TABLE `invite` DROP COLUMN `userLocalPart`", undefined); + await queryRunner.query("ALTER TABLE `profile` ADD CONSTRAINT `FK_a24972ebd73b106250713dcddd9` FOREIGN KEY (`userId`) REFERENCES `user`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION", undefined); + await queryRunner.query("ALTER TABLE `invite` ADD CONSTRAINT `FK_91bfeec7a9574f458e5b592472d` FOREIGN KEY (`userId`) REFERENCES `user`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION", undefined); + } + +} diff --git a/server/src/migration/1575729716556-ADD-TICKET-TYPE.ts b/server/src/migration/1575729716556-ADD-TICKET-TYPE.ts new file mode 100644 index 00000000..74812206 --- /dev/null +++ b/server/src/migration/1575729716556-ADD-TICKET-TYPE.ts @@ -0,0 +1,24 @@ +import {MigrationInterface, QueryRunner} from "typeorm"; + +export class ADDTICKETTYPE1575729716556 implements MigrationInterface { + name = "ADDTICKETTYPE1575729716556"; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query("ALTER TABLE `invite` DROP FOREIGN KEY `FK_9baa86a15b26d03b384e35bc290`", undefined); + await queryRunner.query("ALTER TABLE `invite` DROP COLUMN `ticket`", undefined); + await queryRunner.query("ALTER TABLE `invite` DROP COLUMN `userDomain`", undefined); + await queryRunner.query("ALTER TABLE `invite` DROP COLUMN `userLocalPart`", undefined); + await queryRunner.query("ALTER TABLE `invite` ADD `deletedAt` datetime NULL", undefined); + await queryRunner.query("ALTER TABLE `invite` ADD `ticketId` varchar(255) NOT NULL", undefined); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query("ALTER TABLE `invite` DROP COLUMN `ticketId`", undefined); + await queryRunner.query("ALTER TABLE `invite` DROP COLUMN `deletedAt`", undefined); + await queryRunner.query("ALTER TABLE `invite` ADD `userLocalPart` varchar(64) NULL", undefined); + await queryRunner.query("ALTER TABLE `invite` ADD `userDomain` varchar(255) NULL", undefined); + await queryRunner.query("ALTER TABLE `invite` ADD `ticket` varchar(36) NOT NULL", undefined); + await queryRunner.query("ALTER TABLE `invite` ADD CONSTRAINT `FK_9baa86a15b26d03b384e35bc290` FOREIGN KEY (`userId`, `userLocalPart`, `userDomain`) REFERENCES `user`(`id`,`emailLocalpart`,`emailDomain`) ON DELETE NO ACTION ON UPDATE NO ACTION", undefined); + } + +} \ No newline at end of file diff --git a/server/src/migration/1575997516122-ADD-PHONE-AND-CHANGE-USER-JOIN-COLUMN.ts b/server/src/migration/1575997516122-ADD-PHONE-AND-CHANGE-USER-JOIN-COLUMN.ts new file mode 100644 index 00000000..9f6fe4cd --- /dev/null +++ b/server/src/migration/1575997516122-ADD-PHONE-AND-CHANGE-USER-JOIN-COLUMN.ts @@ -0,0 +1,38 @@ +import {MigrationInterface, QueryRunner} from "typeorm"; + +export class ADDPHONEANDCHANGEUSERJOINCOLUMN1575997516122 implements MigrationInterface { + name = "ADDPHONEANDCHANGEUSERJOINCOLUMN1575997516122"; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query("ALTER TABLE `profile` DROP FOREIGN KEY `FK_56adaed4f38934440c8a88cd50b`", undefined); + await queryRunner.query("ALTER TABLE `profile` DROP COLUMN `userDomain`", undefined); + await queryRunner.query("ALTER TABLE `profile` DROP COLUMN `userLocalPart`", undefined); + await queryRunner.query("ALTER TABLE `profile` ADD `phone` varchar(255) NULL", undefined); + await queryRunner.query("ALTER TABLE `profile` DROP COLUMN `name`", undefined); + await queryRunner.query("ALTER TABLE `profile` ADD `name` varchar(64) NOT NULL", undefined); + await queryRunner.query("ALTER TABLE `profile` DROP COLUMN `status`", undefined); + await queryRunner.query("ALTER TABLE `profile` ADD `status` varchar(128) NULL", undefined); + await queryRunner.query("ALTER TABLE `profile` DROP COLUMN `thumbnail`", undefined); + await queryRunner.query("ALTER TABLE `profile` ADD `thumbnail` varchar(256) NULL DEFAULT '/image/default-thumbnail.jpeg'", undefined); + await queryRunner.query("ALTER TABLE `profile` DROP COLUMN `description`", undefined); + await queryRunner.query("ALTER TABLE `profile` ADD `description` varchar(512) NULL", undefined); + await queryRunner.query("ALTER TABLE `profile` CHANGE `role` `role` enum ('admin', 'member') NOT NULL DEFAULT 'member'", undefined); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query("ALTER TABLE `profile` CHANGE `role` `role` enum ('admin', 'member') NOT NULL", undefined); + await queryRunner.query("ALTER TABLE `profile` DROP COLUMN `description`", undefined); + await queryRunner.query("ALTER TABLE `profile` ADD `description` varchar(255) NULL", undefined); + await queryRunner.query("ALTER TABLE `profile` DROP COLUMN `thumbnail`", undefined); + await queryRunner.query("ALTER TABLE `profile` ADD `thumbnail` varchar(255) NULL", undefined); + await queryRunner.query("ALTER TABLE `profile` DROP COLUMN `status`", undefined); + await queryRunner.query("ALTER TABLE `profile` ADD `status` varchar(255) NOT NULL", undefined); + await queryRunner.query("ALTER TABLE `profile` DROP COLUMN `name`", undefined); + await queryRunner.query("ALTER TABLE `profile` ADD `name` varchar(255) NOT NULL", undefined); + await queryRunner.query("ALTER TABLE `profile` DROP COLUMN `phone`", undefined); + await queryRunner.query("ALTER TABLE `profile` ADD `userLocalPart` varchar(64) NULL", undefined); + await queryRunner.query("ALTER TABLE `profile` ADD `userDomain` varchar(255) NULL", undefined); + await queryRunner.query("ALTER TABLE `profile` ADD CONSTRAINT `FK_56adaed4f38934440c8a88cd50b` FOREIGN KEY (`userId`, `userLocalPart`, `userDomain`) REFERENCES `user`(`id`,`emailLocalpart`,`emailDomain`) ON DELETE NO ACTION ON UPDATE NO ACTION", undefined); + } + +} diff --git a/server/src/migration/1576118484821-ADD-EMAIL-INDEX.ts b/server/src/migration/1576118484821-ADD-EMAIL-INDEX.ts new file mode 100644 index 00000000..b16ce1c5 --- /dev/null +++ b/server/src/migration/1576118484821-ADD-EMAIL-INDEX.ts @@ -0,0 +1,56 @@ +import {MigrationInterface, QueryRunner} from "typeorm"; + +export class ADDEMAILINDEX1576118484821 implements MigrationInterface { + name = "ADDEMAILINDEX1576118484821"; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query("DROP INDEX `FK_9baa86a15b26d03b384e35bc290` ON `invite`", undefined); + await queryRunner.query("DROP INDEX `FK_56adaed4f38934440c8a88cd50b` ON `profile`", undefined); + await queryRunner.query("ALTER TABLE `user` CHANGE `id` `id` int NOT NULL", undefined); + await queryRunner.query("ALTER TABLE `user` DROP PRIMARY KEY", undefined); + await queryRunner.query("ALTER TABLE `user` ADD PRIMARY KEY (`id`, `emailDomain`)", undefined); + await queryRunner.query("ALTER TABLE `user` CHANGE `id` `id` int NOT NULL AUTO_INCREMENT", undefined); + await queryRunner.query("ALTER TABLE `user` CHANGE `id` `id` int NOT NULL", undefined); + await queryRunner.query("ALTER TABLE `user` DROP PRIMARY KEY", undefined); + await queryRunner.query("ALTER TABLE `user` ADD PRIMARY KEY (`id`)", undefined); + await queryRunner.query("ALTER TABLE `user` CHANGE `id` `id` int NOT NULL AUTO_INCREMENT", undefined); + await queryRunner.query("ALTER TABLE `invite` CHANGE `id` `id` int NOT NULL", undefined); + await queryRunner.query("ALTER TABLE `invite` DROP PRIMARY KEY", undefined); + await queryRunner.query("ALTER TABLE `invite` ADD PRIMARY KEY (`id`, `emailDomain`)", undefined); + await queryRunner.query("ALTER TABLE `invite` CHANGE `id` `id` int NOT NULL AUTO_INCREMENT", undefined); + await queryRunner.query("ALTER TABLE `invite` CHANGE `id` `id` int NOT NULL", undefined); + await queryRunner.query("ALTER TABLE `invite` DROP PRIMARY KEY", undefined); + await queryRunner.query("ALTER TABLE `invite` ADD PRIMARY KEY (`id`)", undefined); + await queryRunner.query("ALTER TABLE `invite` CHANGE `id` `id` int NOT NULL AUTO_INCREMENT", undefined); + await queryRunner.query("CREATE UNIQUE INDEX `email_uniq_index` ON `user` (`emailLocalpart`, `emailDomain`)", undefined); + await queryRunner.query("CREATE UNIQUE INDEX `email_uniq_index` ON `invite` (`emailLocalpart`, `emailDomain`)", undefined); + await queryRunner.query("ALTER TABLE `invite` ADD CONSTRAINT `FK_91bfeec7a9574f458e5b592472d` FOREIGN KEY (`userId`) REFERENCES `user`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION", undefined); + await queryRunner.query("ALTER TABLE `profile` ADD CONSTRAINT `FK_a24972ebd73b106250713dcddd9` FOREIGN KEY (`userId`) REFERENCES `user`(`id`) ON DELETE NO ACTION ON UPDATE NO ACTION", undefined); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query("ALTER TABLE `profile` DROP FOREIGN KEY `FK_a24972ebd73b106250713dcddd9`", undefined); + await queryRunner.query("ALTER TABLE `invite` DROP FOREIGN KEY `FK_91bfeec7a9574f458e5b592472d`", undefined); + await queryRunner.query("DROP INDEX `email_uniq_index` ON `invite`", undefined); + await queryRunner.query("DROP INDEX `email_uniq_index` ON `user`", undefined); + await queryRunner.query("ALTER TABLE `invite` CHANGE `id` `id` int NOT NULL", undefined); + await queryRunner.query("ALTER TABLE `invite` DROP PRIMARY KEY", undefined); + await queryRunner.query("ALTER TABLE `invite` ADD PRIMARY KEY (`id`, `emailDomain`)", undefined); + await queryRunner.query("ALTER TABLE `invite` CHANGE `id` `id` int NOT NULL AUTO_INCREMENT", undefined); + await queryRunner.query("ALTER TABLE `invite` CHANGE `id` `id` int NOT NULL", undefined); + await queryRunner.query("ALTER TABLE `invite` DROP PRIMARY KEY", undefined); + await queryRunner.query("ALTER TABLE `invite` ADD PRIMARY KEY (`id`, `emailLocalpart`, `emailDomain`)", undefined); + await queryRunner.query("ALTER TABLE `invite` CHANGE `id` `id` int NOT NULL AUTO_INCREMENT", undefined); + await queryRunner.query("ALTER TABLE `user` CHANGE `id` `id` int NOT NULL", undefined); + await queryRunner.query("ALTER TABLE `user` DROP PRIMARY KEY", undefined); + await queryRunner.query("ALTER TABLE `user` ADD PRIMARY KEY (`id`, `emailDomain`)", undefined); + await queryRunner.query("ALTER TABLE `user` CHANGE `id` `id` int NOT NULL AUTO_INCREMENT", undefined); + await queryRunner.query("ALTER TABLE `user` CHANGE `id` `id` int NOT NULL", undefined); + await queryRunner.query("ALTER TABLE `user` DROP PRIMARY KEY", undefined); + await queryRunner.query("ALTER TABLE `user` ADD PRIMARY KEY (`id`, `emailLocalpart`, `emailDomain`)", undefined); + await queryRunner.query("ALTER TABLE `user` CHANGE `id` `id` int NOT NULL AUTO_INCREMENT", undefined); + await queryRunner.query("CREATE INDEX `FK_56adaed4f38934440c8a88cd50b` ON `profile` (`userId`)", undefined); + await queryRunner.query("CREATE INDEX `FK_9baa86a15b26d03b384e35bc290` ON `invite` (`userId`)", undefined); + } + +} diff --git a/server/src/migration/1576118787009-ADD-TICKET-INDEX.ts b/server/src/migration/1576118787009-ADD-TICKET-INDEX.ts new file mode 100644 index 00000000..c5cd056e --- /dev/null +++ b/server/src/migration/1576118787009-ADD-TICKET-INDEX.ts @@ -0,0 +1,16 @@ +import {MigrationInterface, QueryRunner} from "typeorm"; + +export class ADDTICKETINDEX1576118787009 implements MigrationInterface { + name = "ADDTICKETINDEX1576118787009"; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query("ALTER TABLE `invite` ADD UNIQUE INDEX `IDX_d3c3a6d023f98b06847bf7879a` (`ticketId`)", undefined); + await queryRunner.query("CREATE UNIQUE INDEX `ticket_uniq_index` ON `invite` (`ticketId`)", undefined); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query("DROP INDEX `ticket_uniq_index` ON `invite`", undefined); + await queryRunner.query("ALTER TABLE `invite` DROP INDEX `IDX_d3c3a6d023f98b06847bf7879a`", undefined); + } + +} diff --git a/server/src/model/invite/invite-info.ts b/server/src/model/invite/invite-info.ts new file mode 100644 index 00000000..be5a9317 --- /dev/null +++ b/server/src/model/invite/invite-info.ts @@ -0,0 +1,35 @@ +import { Invite } from "../../domain/entity/Invite"; +import UrlInfo from "../../utils/url-info"; +import _ from "lodash"; + +export class InviteInfo { + private id: number; + private email: string; + private snug: string; + private link: string; + private createdAt: Date; + + private constructor( + id: number, + email: string, + snug: string, + link: string, + createdAt: Date + ) { + this.id = id; + this.email = email; + this.snug = snug; + this.link = link; + this.createdAt = createdAt; + } + + static fromInvite(invite: Invite): InviteInfo { + const { id, ticket, createdAt, email, snug } = invite; + const link = UrlInfo.aboutApiVerification(ticket.getValue()); + return new InviteInfo(id, email.asFormat(), snug.name, link, createdAt); + } +} + +export const toInvitations = (invitations: Invite[]): InviteInfo[] => { + return _.map(invitations, InviteInfo.fromInvite); +}; diff --git a/server/src/model/invite/invitee.ts b/server/src/model/invite/invitee.ts new file mode 100644 index 00000000..4bb34e28 --- /dev/null +++ b/server/src/model/invite/invitee.ts @@ -0,0 +1,34 @@ +import {Invite} from "../../domain/entity/Invite"; +import {IsNull} from "typeorm"; +import {InviteInfo, toInvitations} from "./invite-info"; +import {Ticket} from "../../domain/vo/Ticket"; +import {Profile} from "../../domain/entity/Profile"; +import {Participant} from "../participant/participant"; +import {IsolationLevel, Propagation, Transactional} from "typeorm-transactional-cls-hooked"; +import {SnugInfo} from "../../model/snug/snug-info"; + +export class Invitee { + async findInvitations(userId: string): Promise { + const invitations = await Invite.find({where: {user: userId, deletedAt: IsNull()}}); + return toInvitations(invitations); + } + + @Transactional({propagation: Propagation.REQUIRED, isolationLevel: IsolationLevel.REPEATABLE_READ}) + async joinSnug(ticket: Ticket, agree: boolean): Promise { + const invite = await Invite.findWithUserByTicket(ticket); + const joinedInvitation = await Invite.deleteBy(invite); + if (agree) { + const profile = Profile.builder(joinedInvitation.snug, joinedInvitation.user).build(); + const joinedProfile = await Profile.save(profile); + const participant = new Participant(); + await participant.joinDefaultRoom(joinedProfile); + } + + return SnugInfo.fromSnug(joinedInvitation.snug); + } + + async findInvitationByTicket(ticket: Ticket): Promise { + const invite = await Invite.findByTicket(ticket); + return SnugInfo.fromSnug(invite.snug); + } +} \ No newline at end of file diff --git a/server/src/model/invite/inviter.ts b/server/src/model/invite/inviter.ts new file mode 100644 index 00000000..be5d2c0d --- /dev/null +++ b/server/src/model/invite/inviter.ts @@ -0,0 +1,38 @@ +import {Notifier} from "../notifier/notifier"; +import {Invite} from "../../domain/entity/Invite"; +import {Email} from "../../domain/vo/Email"; +import {Snug} from "../../domain/entity/Snug"; +import {User} from "../../domain/entity/User"; +import {InviteInfo, toInvitations} from "./invite-info"; +import _ from "lodash"; + +export class Inviter { + private emailNotifier: Notifier; + private alarmNotifier: Notifier; + + constructor(emailNotifier: Notifier, alarmNotifier: Notifier) { + this.emailNotifier = emailNotifier; + this.alarmNotifier = alarmNotifier; + } + + async invite(snugId: string, emails: string[]): Promise { + const snug = await Snug.findOneOrFail(snugId); + const signedInvitees = await User.findByEmails(emails); + const unsignedInvitees = _.differenceWith(emails, signedInvitees, (email, user) => user.hasSameEmail(email)) + .map(email => Email.from(email)) + .map(email => new User(email)); + + const invitationsForSignedPeople = this.makeInvitations(signedInvitees, snug); + const invitationsForUnsignedPeople = this.makeInvitations(unsignedInvitees, snug); + const invitations = _.union(invitationsForSignedPeople, invitationsForUnsignedPeople); + const invitationsToNotifier = await Invite.save(invitations); + + this.emailNotifier.send(invitationsToNotifier); + this.alarmNotifier.send(invitationsForSignedPeople); + return toInvitations(invitationsToNotifier); + } + + private makeInvitations(users: User[], snug: Snug): Invite[] { + return _.map(users, (user) => new Invite(user, snug)); + } +} \ No newline at end of file diff --git a/server/src/model/notifier/email-notifier.ts b/server/src/model/notifier/email-notifier.ts new file mode 100644 index 00000000..b6b9a64c --- /dev/null +++ b/server/src/model/notifier/email-notifier.ts @@ -0,0 +1,17 @@ +import {Notifier} from "./notifier"; +import {Email} from "../../domain/vo/Email"; +import {publish} from "../../mail/mail-manager"; +import {Invite} from "../../domain/entity/Invite"; +import _ from "lodash"; + +export class EmailNotifier implements Notifier { + public send(invitations: Invite[]): boolean { + const emails = _.map(invitations, this.addContentsToEmail); + return publish([...emails]); + } + + private addContentsToEmail(invite: Invite): Email { + const {email} = invite; + return Email.from(email.asFormat(), invite.provideContents()); + } +} \ No newline at end of file diff --git a/server/src/model/notifier/invite-notifier.ts b/server/src/model/notifier/invite-notifier.ts new file mode 100644 index 00000000..885120a6 --- /dev/null +++ b/server/src/model/notifier/invite-notifier.ts @@ -0,0 +1,17 @@ +import {Notifier} from "./notifier"; +import {Invite} from "../../domain/entity/Invite"; +import {publishIO} from "../../socket/socket-manager"; +import {tellInvitation} from "../../socket/action/invite"; +import {InviteInfo} from "../../model/invite/invite-info"; +import _ from "lodash"; + +export class InviteNotifier implements Notifier { + public send(invitations: Invite[]): boolean { + return _.every(invitations, this.generate); + } + + private generate(invite: Invite): boolean { + const inviteInfo = InviteInfo.fromInvite(invite); + return tellInvitation(invite.user.id, inviteInfo, publishIO().of("/user")); + } +} \ No newline at end of file diff --git a/server/src/model/notifier/notifier.ts b/server/src/model/notifier/notifier.ts new file mode 100644 index 00000000..8f939b76 --- /dev/null +++ b/server/src/model/notifier/notifier.ts @@ -0,0 +1,3 @@ +export interface Notifier { + send(data: T): boolean; +} \ No newline at end of file diff --git a/server/src/model/participant/participant.ts b/server/src/model/participant/participant.ts new file mode 100644 index 00000000..b710bd1c --- /dev/null +++ b/server/src/model/participant/participant.ts @@ -0,0 +1,13 @@ +import {Profile} from "../../domain/entity/Profile"; +import {Room} from "../../domain/entity/Room"; +import {ParticipateIn} from "../../domain/entity/ParticipateIn"; +import {IsolationLevel, Propagation, Transactional} from "typeorm-transactional-cls-hooked"; + +export class Participant { + @Transactional({propagation: Propagation.REQUIRED, isolationLevel: IsolationLevel.REPEATABLE_READ}) + public async joinDefaultRoom(profile: Profile): Promise { + const room = await Room.findDefaultChannelBySnug(profile.snug); + const participateIn = new ParticipateIn(profile, room); + return await ParticipateIn.save(participateIn); + } +} \ No newline at end of file diff --git a/server/src/model/profile/profile-info.ts b/server/src/model/profile/profile-info.ts new file mode 100644 index 00000000..1de0cfc4 --- /dev/null +++ b/server/src/model/profile/profile-info.ts @@ -0,0 +1,72 @@ +import { Profile, UserRole } from "../../domain/entity/Profile"; +import _ from "lodash"; + +export class ProfileInfo { + private id: number; + private name: string; + private phone: string; + private status: string; + private thumbnail: string; + private description: string; + private role: UserRole; + private updatedAt: Date; + private email: string; + private snugId: number; + + private constructor( + id: number, + name: string, + phone: string, + status: string, + thumbnail: string, + description: string, + role: UserRole, + updatedAt: Date, + email?: string, + snugId?: number + ) { + this.id = id; + this.name = name; + this.phone = phone; + this.status = status; + this.thumbnail = thumbnail; + this.description = description; + this.role = role; + this.updatedAt = updatedAt; + this.email = email; + this.snugId = snugId; + } + + static fromProfile(profile: Profile): ProfileInfo { + const { + id, + name, + status, + phone, + thumbnail, + description, + role, + updatedAt, + user, + snug + } = profile; + const email = user && user.email.asFormat(); + const snugId = snug && snug.id; + return new ProfileInfo( + id, + name, + phone, + status, + thumbnail, + description, + role, + updatedAt, + email, + snugId + ); + } + + public asObject(): object { + return _.toPlainObject(this); + } +} diff --git a/server/src/model/profile/profiler.ts b/server/src/model/profile/profiler.ts new file mode 100644 index 00000000..ee727fe3 --- /dev/null +++ b/server/src/model/profile/profiler.ts @@ -0,0 +1,15 @@ +import {Profile} from "../../domain/entity/Profile"; +import {ProfileInfo} from "./profile-info"; + +export class Profiler { + public async update(id: string, profile: Profile): Promise { + const profileModel = await Profile.findById(id); + const profileRevision = await Profile.merge(profileModel, profile).save(); + return ProfileInfo.fromProfile(profileRevision); + } + + public async findById(profileId: string): Promise { + const profile = await Profile.findById(profileId); + return ProfileInfo.fromProfile(profile); + } +} \ No newline at end of file diff --git a/server/src/model/snug/snug-info.ts b/server/src/model/snug/snug-info.ts new file mode 100644 index 00000000..57667003 --- /dev/null +++ b/server/src/model/snug/snug-info.ts @@ -0,0 +1,26 @@ +import UrlInfo from "../../utils/url-info"; +import {Snug} from "../../domain/entity/Snug"; + +export class SnugInfo { + private id: number; + private name: string; + private thumbnail: string; + private description: string; + private link: string; + private createdAt: Date; + + private constructor(id: number, name: string, thumbnail: string, description: string, link: string, createdAt: Date) { + this.id = id; + this.name = name; + this.thumbnail = thumbnail; + this.description = description; + this.link = link; + this.createdAt = createdAt; + } + + static fromSnug(snug: Snug): SnugInfo { + const {id, name, createdAt, thumbnail, description} = snug; + const link = UrlInfo.aboutSnugById(snug.id); + return new SnugInfo(id, name, thumbnail, description, link, createdAt); + } +} \ No newline at end of file diff --git a/server/src/routes/apiRouter.ts b/server/src/routes/apiRouter.ts new file mode 100644 index 00000000..3a77e4b3 --- /dev/null +++ b/server/src/routes/apiRouter.ts @@ -0,0 +1,22 @@ +import { Router } from "express"; +import postRouter from "./post/post-router"; +import channelRouter from "./channel/channel-router"; +import snugRouter from "./snug/snug-router"; +import userRouter from "./user/user-router"; +import authRouter from "./auth/auth-router"; +import inviteRouter from "./invite/invite-router"; +import profileRouter from "./profile/profile-router"; +import participateInRouter from "./participate-in/index"; + +const router = Router(); + +router.use("/posts", postRouter); +router.use("/channels", channelRouter); +router.use("/snugs", snugRouter); +router.use("/auth", authRouter); +router.use("/users", userRouter); +router.use("/invite", inviteRouter); +router.use("/profiles", profileRouter); +router.use("/participateIns", participateInRouter); + +export default router; diff --git a/server/src/routes/auth/auth-router.ts b/server/src/routes/auth/auth-router.ts new file mode 100644 index 00000000..d140a763 --- /dev/null +++ b/server/src/routes/auth/auth-router.ts @@ -0,0 +1,10 @@ +import { Router } from "express"; +import * as AuthApiController from "../../controller/api/auth-controller"; + +const router = Router(); + +router.post("/login", AuthApiController.login); + +router.get("/snugs/:snugId/profiles", AuthApiController.getProfileToken); + +export default router; diff --git a/server/src/routes/channel/channel-router.ts b/server/src/routes/channel/channel-router.ts index dea32353..2dc59e26 100644 --- a/server/src/routes/channel/channel-router.ts +++ b/server/src/routes/channel/channel-router.ts @@ -1,9 +1,9 @@ -import {Router} from "express"; +import { Router } from "express"; import * as ChannelApiController from "../../controller/api/channel-controller"; import PostRouter from "./post/post-router"; -import {isNumeric} from "../../validator/identifier-validator"; +import { isNumeric } from "../../middleware/validator"; -const router = Router({mergeParams: true}); +const router = Router({ mergeParams: true }); /** * @@ -11,25 +11,23 @@ const router = Router({mergeParams: true}); * channel controller 의 find() 메소드 호출 * * */ -router.route("/:title") - .get(ChannelApiController.find); +router.route("/:title").get(ChannelApiController.find); - -router.route("/") - .get(ChannelApiController.findAll) - .post(ChannelApiController.create); +router.route("/").post(ChannelApiController.create); /** * * /api/channels/:id/posts 경로 매핑 * * */ -router.use("/:id/posts", PostRouter); +router.use("/:channelId/posts", PostRouter); + +router.post("/join", ChannelApiController.join); /** * * isNumber() 메소드에서 path variable 인 id 대한 유효성 검사 * * */ -router.param("id", isNumeric); +router.param("channelId", isNumeric); export default router; diff --git a/server/src/routes/index.ts b/server/src/routes/index.ts new file mode 100644 index 00000000..6403dfb0 --- /dev/null +++ b/server/src/routes/index.ts @@ -0,0 +1,12 @@ +import { Router } from "express"; +import * as IndexController from "../controller/index-controller"; +import * as InviteController from "../controller/api/invite-controller"; + +const router = Router(); + +router + .route("/invite/:ticket") + .post(InviteController.verify, InviteController.redirectBySnug); + +router.get("/", IndexController.index); +export default router; diff --git a/server/src/routes/invite/invite-router.ts b/server/src/routes/invite/invite-router.ts new file mode 100644 index 00000000..d55a3c64 --- /dev/null +++ b/server/src/routes/invite/invite-router.ts @@ -0,0 +1,9 @@ +import {Router} from "express"; +import * as InviteApiController from "../../controller/api/invite-controller"; + +const router = Router({mergeParams: true}); + +router.route("/:ticket") + .post(InviteApiController.verify, InviteApiController.responseBySnug); + +export default router; diff --git a/server/src/routes/participate-in/index.ts b/server/src/routes/participate-in/index.ts new file mode 100644 index 00000000..7fdb741a --- /dev/null +++ b/server/src/routes/participate-in/index.ts @@ -0,0 +1,13 @@ +import { + isVerifyLogined, + isVerifyProfile +} from "../../validator/identifier-validator"; +import { Router } from "express"; +import * as ParticipateInController from "../../controller/api/participate-in-controller"; +const router = Router(); + +router.use(isVerifyLogined); + +router.get("/", isVerifyProfile, ParticipateInController.getChannels); + +export default router; diff --git a/server/src/routes/profile/profile-router.ts b/server/src/routes/profile/profile-router.ts new file mode 100644 index 00000000..21683591 --- /dev/null +++ b/server/src/routes/profile/profile-router.ts @@ -0,0 +1,9 @@ +import {Router} from "express"; +import * as ProfileApiController from "../../controller/api/profile-controller"; + +const router = Router({mergeParams: true}); +router.use("/:profileId", ProfileApiController.isAccessibleProfile); +router.route("/:profileId") + .get(ProfileApiController.findById) + .patch(ProfileApiController.update); +export default router; \ No newline at end of file diff --git a/server/src/routes/snug/channel/channel-router.ts b/server/src/routes/snug/channel/channel-router.ts new file mode 100644 index 00000000..aa89ef55 --- /dev/null +++ b/server/src/routes/snug/channel/channel-router.ts @@ -0,0 +1,7 @@ +import { Router } from "express"; +import * as ChannelApiController from "../../../controller/api/channel-controller"; + +const router = Router({mergeParams: true}); + +router.get("/", ChannelApiController.findAll); +export default router; \ No newline at end of file diff --git a/server/src/routes/snug/invite/invite-router.ts b/server/src/routes/snug/invite/invite-router.ts new file mode 100644 index 00000000..d0ec3528 --- /dev/null +++ b/server/src/routes/snug/invite/invite-router.ts @@ -0,0 +1,8 @@ +import { Router } from "express"; +import * as InviteApiController from "../../../controller/api/invite-controller"; +import {isValidInviteForm} from "../../../middleware/validator"; + +const router = Router({mergeParams: true}); + +router.post("/", isValidInviteForm, InviteApiController.invite); +export default router; \ No newline at end of file diff --git a/server/src/routes/snug/snug-router.ts b/server/src/routes/snug/snug-router.ts new file mode 100644 index 00000000..5e667693 --- /dev/null +++ b/server/src/routes/snug/snug-router.ts @@ -0,0 +1,18 @@ +import { Router } from "express"; +import { create, findByUserId } from "../../controller/api/snug-controller"; +import channelRouter from "./channel/channel-router"; +import inviteRouter from "./invite/invite-router"; +import { isNumeric } from "../../validator/identifier-validator"; + +const router = Router({ mergeParams: true }); + +router.use("/:snugId/channels", channelRouter); + +router.use("/:snugId/invite", inviteRouter); + +router.route("/") + .get(findByUserId) + .post(create); + +router.param("snugId", isNumeric); +export default router; diff --git a/server/src/routes/user/invite/invite-router.ts b/server/src/routes/user/invite/invite-router.ts new file mode 100644 index 00000000..f6e2e3e0 --- /dev/null +++ b/server/src/routes/user/invite/invite-router.ts @@ -0,0 +1,9 @@ +import {Router} from "express"; +import * as InviteApiController from "../../../controller/api/invite-controller"; + +const router = Router({mergeParams: true}); + +router.route("/") + .get(InviteApiController.findInvitations); + +export default router; \ No newline at end of file diff --git a/server/src/routes/user/user-router.ts b/server/src/routes/user/user-router.ts new file mode 100644 index 00000000..2c62ebc7 --- /dev/null +++ b/server/src/routes/user/user-router.ts @@ -0,0 +1,11 @@ +import { Router } from "express"; +import inviteRouter from "./invite/invite-router"; +import * as UserApiController from "../../controller/api/user-controller"; +import { isValidUserForm } from "../../middleware/validator"; + +const router = Router({mergeParams: true}); + +router.post("/", isValidUserForm, UserApiController.create); +router.get("/email/:email", UserApiController.findByEmail); +router.use("/:userId/invite", inviteRouter); +export default router; diff --git a/server/src/server.ts b/server/src/server.ts index 7095f061..4b5f7772 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -1,12 +1,13 @@ import Application from "./app"; -import {Express} from "express"; -import {Server} from "http"; -import {initialize} from "./socket/socket-manager"; +import { Express } from "express"; +import { Server } from "http"; +import { initialize } from "./socket/socket-manager"; +import { initializeMailManger } from "./mail/mail-manager"; -Application.start() - .then((app: Express) => { - const server: Server = app.listen(app.get("port"), () => { - console.log("listen port", app.get("port")); - initialize(server); - }); - }); \ No newline at end of file +Application.start().then((app: Express) => { + const server: Server = app.listen(app.get("port"), () => { + console.log("listen port", app.get("port")); + initialize(server); + initializeMailManger(); + }); +}); diff --git a/server/src/socket/action/invite.ts b/server/src/socket/action/invite.ts new file mode 100644 index 00000000..c849e5fc --- /dev/null +++ b/server/src/socket/action/invite.ts @@ -0,0 +1,14 @@ +import SocketIO from "socket.io"; +import {PUBLISH_EVENT} from "../../socket/common/events/publish-type"; +import ResponseForm from "../../utils/response-form"; +import {InviteInfo} from "../../model/invite/invite-info"; + +export const tellInvitation = (userId: number, invite: InviteInfo, userNamespace: SocketIO.Namespace): boolean => { + try { + return userNamespace.in(userId.toString()) + .emit(PUBLISH_EVENT.TELL_INVITATION, ResponseForm.of("tell invite", invite)); + } catch (error) { + console.error(error); + return false; + } +}; \ No newline at end of file diff --git a/server/src/socket/action/room.ts b/server/src/socket/action/snug.ts similarity index 95% rename from server/src/socket/action/room.ts rename to server/src/socket/action/snug.ts index 124c4bba..67331122 100644 --- a/server/src/socket/action/room.ts +++ b/server/src/socket/action/snug.ts @@ -1,4 +1,4 @@ -import {Room} from "../../entity/Room"; +import {Room} from "../../domain/entity/Room"; import SocketIO from "socket.io"; const takeId = (room: Room): string => room.id.toString(); @@ -13,6 +13,7 @@ export const join = async (socket: SocketIO.Socket, profileId: string): Promise< rooms.map(takeId) .forEach(roomId => { socket.join(roomId); + }); } catch (error) { console.error(error); diff --git a/server/src/socket/common/events/publish-type.ts b/server/src/socket/common/events/publish-type.ts index 97db3d9e..314667f7 100644 --- a/server/src/socket/common/events/publish-type.ts +++ b/server/src/socket/common/events/publish-type.ts @@ -1,3 +1,4 @@ export enum PUBLISH_EVENT { - SEND_MESSAGE = "newPost" + SEND_MESSAGE = "newPost", + TELL_INVITATION = "tellInvitation" } \ No newline at end of file diff --git a/server/src/socket/listener/connection.ts b/server/src/socket/listener/connection.ts index bd057c27..2cc21d54 100644 --- a/server/src/socket/listener/connection.ts +++ b/server/src/socket/listener/connection.ts @@ -1,9 +1,12 @@ import SocketIO from "socket.io"; -import * as room from "../action/room"; +import * as room from "../action/snug"; import {CONSUME_EVENT} from "../common/events/consume-type"; export const connect = (io: SocketIO.Server) => { - io.on(CONSUME_EVENT.CONNECTION, (socket: SocketIO.Socket) => { + const snugIo = io.of("/snug"); + const userIo = io.of("/user"); + + snugIo.on(CONSUME_EVENT.CONNECTION, (socket: SocketIO.Socket) => { const req = socket.request; const { headers: { referer } } = req; console.log(`${socket.id} ${referer} 클라이언트 접속`); @@ -17,4 +20,17 @@ export const connect = (io: SocketIO.Server) => { }); }); + userIo.on(CONSUME_EVENT.CONNECTION, (socket: SocketIO.Socket) => { + const req = socket.request; + const { headers: { referer } } = req; + console.log(`${socket.id} ${referer} 클라이언트 접속`); + + socket.on("login", ({userId}) => { + socket.join(userId); + socket.on(CONSUME_EVENT.DISCONNECTION, () => { + console.log(`${socket.id} ${referer} 클라이언트 나감`); + socket.leave(userId); + }); + }); + }); }; \ No newline at end of file diff --git a/server/src/template/email-contents.ts b/server/src/template/email-contents.ts new file mode 100644 index 00000000..727f82c3 --- /dev/null +++ b/server/src/template/email-contents.ts @@ -0,0 +1,40 @@ +export class EmailContents { + static getTemplateForVerification(snugName: string, link: string): string { + return ` +
+
+ +
+
Snug ${snugName}
+
+
당신은 ${snugName}에 초대되었습니다. 초대를 수락하시겠습니까?
+
+
+
+ + +
+
+
+`; + } + + static getTemplateForRegister(snugName: string, link: string): string { + return ` +
+
+ +
+
Snug ${snugName}
+
+
당신은 ${snugName}에 초대되었습니다. 초대를 수락하시겠습니까?
+
+ +
+`; + } +} \ No newline at end of file diff --git a/server/src/utils/array-helper.ts b/server/src/utils/array-helper.ts new file mode 100644 index 00000000..125e719d --- /dev/null +++ b/server/src/utils/array-helper.ts @@ -0,0 +1,7 @@ +export const isLongerThan = (array: object[], expected: number): boolean => { + return array && array.length > expected; +}; + +export const isNotEmpty = (array: object[]): boolean => { + return isLongerThan(array, 0); +}; \ No newline at end of file diff --git a/server/src/util/HttpException.ts b/server/src/utils/exception/HttpException.ts similarity index 73% rename from server/src/util/HttpException.ts rename to server/src/utils/exception/HttpException.ts index 173adca3..00c48e0a 100644 --- a/server/src/util/HttpException.ts +++ b/server/src/utils/exception/HttpException.ts @@ -1,7 +1,7 @@ export default class HttpException extends Error { public status?: number; - constructor(message: string, status?: number,) { + constructor(message: string, status?: number) { super(message); this.status = status; } diff --git a/server/src/utils/exception/InvalidEmailException.ts b/server/src/utils/exception/InvalidEmailException.ts new file mode 100644 index 00000000..bc62df90 --- /dev/null +++ b/server/src/utils/exception/InvalidEmailException.ts @@ -0,0 +1,5 @@ +export default class InvalidEmailException extends Error { + constructor(message: string) { + super(message); + } +} diff --git a/server/src/utils/exception/TransferEmailException.ts b/server/src/utils/exception/TransferEmailException.ts new file mode 100644 index 00000000..60ba1ce1 --- /dev/null +++ b/server/src/utils/exception/TransferEmailException.ts @@ -0,0 +1,5 @@ +export default class TransferEmailException extends Error { + constructor(message: string) { + super(message); + } +} \ No newline at end of file diff --git a/server/src/utils/logger.ts b/server/src/utils/logger.ts new file mode 100644 index 00000000..dd68d6dc --- /dev/null +++ b/server/src/utils/logger.ts @@ -0,0 +1,19 @@ +import winston from "winston"; +import { createLogger, format, transports } from "winston"; + +const options: winston.LoggerOptions = { + level: "info", + format: format.json(), + transports: [ + new transports.File({ filename: "combined.log" }), + new transports.File({ filename: "error.log", level: "error" }) + ] +}; + +const logger = createLogger(options); + +if (process.env.NODE_ENV !== "production") { + logger.add(new transports.Console({ format: format.simple() })); +} + +export default logger; diff --git a/server/src/utils/password/generate-password.ts b/server/src/utils/password/generate-password.ts new file mode 100644 index 00000000..293fd6a1 --- /dev/null +++ b/server/src/utils/password/generate-password.ts @@ -0,0 +1,5 @@ +import bcrypt from "bcryptjs"; + +export const generateHashedPassword = async (password: string) => { + return await bcrypt.hash(password, process.env.PASSWORD_SALT); +}; diff --git a/server/src/utils/url-info.ts b/server/src/utils/url-info.ts new file mode 100644 index 00000000..fe25e20b --- /dev/null +++ b/server/src/utils/url-info.ts @@ -0,0 +1,27 @@ +export default class UrlInfo { + static aboutRegister(): string { + return `${process.env.CLIENT_DOMAIN}/register-user`; + }; + + static aboutApiVerification(ticket: string): string { + return `/api/invite/${ticket}`; + } + + static aboutVerification(ticket: string): string { + const serverDomain = UrlInfo.aboutServerDomain(); + return `${serverDomain}/invite/${ticket}`; + } + + static aboutSnugById(snugId: number): string { + const clientHome = UrlInfo.aboutHome(); + return `${clientHome}/snug/${snugId}`; + } + + static aboutServerDomain(): string { + return `${process.env.HOST}/${process.env.PORT}`; + } + + static aboutHome(): string { + return process.env.CLIENT_DOMAIN; + } +} \ No newline at end of file diff --git a/server/src/validator/email-validator.ts b/server/src/validator/email-validator.ts new file mode 100644 index 00000000..ce1bd3d9 --- /dev/null +++ b/server/src/validator/email-validator.ts @@ -0,0 +1,25 @@ +/** + * + * email이 유효한 형식(XXX@XXX.XXX) 검사 + * @param email string + * + * */ +export const validateEmail = (email: string) => { + const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return re.test(email); +}; + +export const checkInvalidEmail = (email: string) => { + return !validateEmail(email); +}; + +/** + * + * password가 8자리 이상 문자열 여부 확인 + * @param string string + * + * */ + +export const validatePasswordLength = (password: string) => { + return password.length >= 8; +}; diff --git a/server/src/validator/identifier-validator.ts b/server/src/validator/identifier-validator.ts index d0120f08..9004e15f 100644 --- a/server/src/validator/identifier-validator.ts +++ b/server/src/validator/identifier-validator.ts @@ -1,4 +1,6 @@ -import {NextFunction, Request, Response} from "express"; +import { NextFunction, Request, Response } from "express"; +import jwt from "jsonwebtoken"; +import { User } from "../domain/entity/User"; enum Numbers { MIN_CHARACTER_DIGIT = 0, @@ -17,7 +19,9 @@ enum Numbers { * */ export const isOutOfRangeChar = (character: string): boolean => { const digit = parseInt(character); - return !(Numbers.MIN_CHARACTER_DIGIT <= digit && digit <= Numbers.MAX_CHARACTER_DIGIT); + return !( + Numbers.MIN_CHARACTER_DIGIT <= digit && digit <= Numbers.MAX_CHARACTER_DIGIT + ); }; /** @@ -70,10 +74,64 @@ export const isOutOfRange = (target: string): boolean => { * @param id * * */ -export const isNumeric = (request: Request, response: Response, next: NextFunction, id: string) => { - if(hasNotValue(id) || hasNotEveryNumber(id) || isOutOfRange(id)) { +export const isNumeric = ( + request: Request, + response: Response, + next: NextFunction, + id: string +) => { + if (hasNotValue(id) || hasNotEveryNumber(id) || isOutOfRange(id)) { return next("Invalid id format. Must be an Number"); } next(); -}; \ No newline at end of file +}; + +export const offerTokenInfo = (request: Request): UserInfo => { + const token = request.headers["auth-token"]; + if (!token) throw new Error("토큰이 존재하지 않습니다."); + const decoded = jwt.verify(token, process.env.SECRET_KEY); + return decoded; +}; + +export const offerProfileTokenInfo = (request: Request) => { + const token = request.cookies["profile"]; + if (!token) throw new Error("토큰이 존재하지 않습니다."); + const decoded = jwt.verify(token, process.env.SECRET_KEY); + return decoded; +}; + +export const isVerifyLogined = async ( + request: Request, + response: Response, + next: NextFunction +) => { + try { + const decoded = offerTokenInfo(request); + const result = await User.findOne({ where: { email: decoded.email } }); + if (!result) throw new Error("없는 유저입니다."); + next(); + } catch (error) { + next(error); + } +}; + +export const isVerifyProfile = async ( + request: Request, + response: Response, + next: NextFunction +) => { + try { + const decoded = offerProfileTokenInfo(request); + if (typeof decoded != "object") throw new Error("토큰이 잘 못 되었습니다."); + next(); + } catch (error) { + next(error); + } +}; + +export type UserInfo = { + id: number; + name: string; + email: string; +}; diff --git a/server/test/integrate/channel/channel-controller.test.ts b/server/test/integrate/channel/channel-controller.test.ts index 0d4a1c39..ec544b73 100644 --- a/server/test/integrate/channel/channel-controller.test.ts +++ b/server/test/integrate/channel/channel-controller.test.ts @@ -1,7 +1,7 @@ import request from "supertest"; import {SuperTest, Test} from "supertest"; import Application from "../../../src/app"; -import {Room} from "../../../src/entity/Room"; +import {Room} from "../../../src/domain/entity/Room"; import {runInTransaction, initialiseTestTransactions} from "typeorm-test-transactions"; import { ALREADY_EXIST_CHANNEL, diff --git a/server/test/integrate/channel/post/post-controller.test.ts b/server/test/integrate/channel/post/post-controller.test.ts index a152988f..a9570bb6 100644 --- a/server/test/integrate/channel/post/post-controller.test.ts +++ b/server/test/integrate/channel/post/post-controller.test.ts @@ -1,9 +1,9 @@ import request from "supertest"; import {SuperTest, Test} from "supertest"; import Application from "../../../../src/app"; -import {Room} from "../../../../src/entity/Room"; +import {Room} from "../../../../src/domain/entity/Room"; import {runInTransaction, initialiseTestTransactions} from "typeorm-test-transactions"; -import {Post} from "../../../../src/entity/Post"; +import {Post} from "../../../../src/domain/entity/Post"; import {FOUND_CHANNEL} from "../../../../src/controller/api/common/error-message"; initialiseTestTransactions(); @@ -38,7 +38,7 @@ const parsePosts = (posts: Post[]) => { }; describe("Test /api/channels", () => { - describe("Test GET /:id/posts", () => { + describe("Test GET /:channelId/posts", () => { let app: SuperTest; beforeAll(done => { diff --git a/server/test/unit/controller/api/common/order.test.ts b/server/test/unit/controller/api/common/order.test.ts index 385185f3..7fde5b39 100644 --- a/server/test/unit/controller/api/common/order.test.ts +++ b/server/test/unit/controller/api/common/order.test.ts @@ -7,9 +7,9 @@ describe("Test Order", () => { expect(order.add("", "DESC").support()).toEqual({order: {}}); }); - test("ASC or DESC 가 아닌 값이 value 로 입력된 경우, default 인 ASC 가 설정되어야 한다", () => { + test("ASC or DESC 가 아닌 값이 value 로 입력된 경우, default 인 DESC 가 설정되어야 한다", () => { const order = new Order(); - expect(order.add("first", "wrong_value").support()).toEqual({order: {first: "ASC"}}); + expect(order.add("first", "wrong_value").support()).toEqual({order: {first: "DESC"}}); }); test("ASC 가 value 로 입력된 경우, ASC 가 설정되어야 한다", () => { diff --git a/server/test/unit/controller/api/common/paginator.test.ts b/server/test/unit/controller/api/common/paginator.test.ts deleted file mode 100644 index 3cda254b..00000000 --- a/server/test/unit/controller/api/common/paginator.test.ts +++ /dev/null @@ -1,51 +0,0 @@ -import {Paginator} from "../../../../../src/controller/api/common/paginator"; - -describe("Test Paginator", () => { - describe("Test support() method", () => { - const [defaultPage, defaultSize] = Paginator.getDefaultValues(); - test("올바른 page, size 입력한 경우, 테스트를 통과해야 한다", () => { - const pageable = new Paginator({page: 3, size: 2}); - expect(pageable.addOrder("", "").support()).toEqual({skip: 3, take: 2, order: {}}); - }); - - test("size 가 null 인 경우, take 는 default 값으로 설정되어야 한다", () => { - const pageable = new Paginator({page: 3, size: null}); - expect(pageable.addOrder("", "").support()).toEqual({skip: 3, take: defaultSize, order: {}}); - }); - - test("page 가 null 인 경우, skip 는 default 값으로 설정되어야 한다", () => { - const pageable = new Paginator({page: null, size: 2}); - expect(pageable.addOrder("", "").support()).toEqual({skip: defaultPage, take: 2, order: {}}); - }); - - test("page, size 모두 null 인 경우, take & skip 모두 default 값으로 설정되어야 한다", () => { - const pageable = new Paginator({page: null, size: null}); - expect(pageable.addOrder("", "").support()).toEqual({skip: defaultPage, take: defaultSize, order: {}}); - }); - - test("order value 에 빈 문자열이 입력된 경우, default 인 ASC 가 설정되어야 한다", () => { - const pageable = new Paginator({page: 3, size: 2}); - expect(pageable.addOrder("id", "").support()).toEqual({skip: 3, take: 2, order: {id: "ASC"}}); - }); - - test("order 의 value 를 ASC 로 입력한 경우, ASC 가 설정되어야 한다", () => { - const pageable = new Paginator({page: 3, size: 2}); - expect(pageable.addOrder("id", "ASC").support()).toEqual({skip: 3, take: 2, order: {id: "ASC"}}); - }); - - test("order 의 value 를 DESC 로 입력한 경우, DESC 가 설정되어야 한다", () => { - const pageable = new Paginator({page: 3, size: 2}); - expect(pageable.addOrder("id", "DESC").support()).toEqual({skip: 3, take: 2, order: {id: "DESC"}}); - }); - - test("order 에 동일한 key 대해 다른 value 가 입력된 경우, 첫 번째로 설정된 value 가 설정되어야 한다", () => { - const pageable = new Paginator({page: 3, size: 2}); - expect(pageable.addOrder("id", "DESC").addOrder("id", "ASC").support()).toEqual({skip: 3, take: 2, order: {id: "DESC"}}); - }); - - test("order 에 여러 가지의 정렬 조건이 입력된 경우, 모두 결과에 포함되어야 한다", () => { - const pageable = new Paginator({page: 3, size: 2}); - expect(pageable.addOrder("id", "DESC").addOrder("name", "ASC").support()).toEqual({skip: 3, take: 2, order: {id: "DESC", name: "ASC"}}); - }); - }); -}); \ No newline at end of file diff --git a/server/test/unit/controller/channel-controller.test.ts b/server/test/unit/controller/channel-controller.test.ts index d00c76cd..19fe91af 100644 --- a/server/test/unit/controller/channel-controller.test.ts +++ b/server/test/unit/controller/channel-controller.test.ts @@ -1,5 +1,5 @@ import * as ChannelApiController from "../../../src/controller/api/channel-controller"; -import {Room} from "../../../src/entity/Room"; +import {Room} from "../../../src/domain/entity/Room"; import {FOUND_CHANNEL, NOT_FOUND_CHANNEL} from "../../../src/controller/api/common/error-message"; jest.mock( "../../../src/entity/Room"); diff --git a/server/test/unit/controller/post-controller.test.ts b/server/test/unit/controller/post-controller.test.ts index 9fbb2b3c..5ac15044 100644 --- a/server/test/unit/controller/post-controller.test.ts +++ b/server/test/unit/controller/post-controller.test.ts @@ -1,5 +1,5 @@ import * as PostApiController from "../../../src/controller/api/post-controller"; -import {Post} from "../../../src/entity/Post"; +import {Post} from "../../../src/domain/entity/Post"; jest.mock( "../../../src/entity/Post"); import {mockRequest, mockResponse} from "mock-req-res"; import {FOUND_CHANNEL} from "../../../src/controller/api/common/error-message";