diff --git a/frontend/.eslintignore b/frontend/.eslintignore new file mode 100644 index 0000000..5827a85 --- /dev/null +++ b/frontend/.eslintignore @@ -0,0 +1,2 @@ +*.css +*.scss \ No newline at end of file diff --git a/frontend/.eslintrc.json b/frontend/.eslintrc.json index 441450d..84236db 100644 --- a/frontend/.eslintrc.json +++ b/frontend/.eslintrc.json @@ -53,6 +53,7 @@ "@typescript-eslint/require-await": "off", "@typescript-eslint/no-unsafe-member-access": "off", "@typescript-eslint/no-unsafe-assignment": "off", - "@typescript-eslint/no-unsafe-call": "off" + "@typescript-eslint/no-unsafe-call": "off", + "@typescript-eslint/unbound-method": "off" } } \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index 5f50368..ae494bb 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -3,7 +3,8 @@ "scripts": { "start": "parcel serve src/index.html", "build": "parcel build src/index.html", - "lint": "eslint ./src/** --ext .js,.jsx,.ts,.tsx", + "lint": "eslint ./src/** --ext .js,.jsx,.ts,.tsx && tsc --noEmit", + "lint-fix": "eslint ./src/** --ext .js,.jsx,.ts,.tsx --fix", "test": "jest" }, "postcss": { @@ -61,4 +62,4 @@ "@types/react-router-dom": "^5.1.6", "@types/sass": "^1.16.0" } -} +} \ No newline at end of file diff --git a/frontend/src/Auth/AuthScreen.tsx b/frontend/src/Auth/AuthScreen.tsx index 113c190..2d2c986 100644 --- a/frontend/src/Auth/AuthScreen.tsx +++ b/frontend/src/Auth/AuthScreen.tsx @@ -23,7 +23,7 @@ export class AuthScreenComponent extends React.PureComponent { } public render() { const { location } = this.props.history; - const { from } = this.props.location.state || { from: "/" }; + const { from } = (this.props.location.state as any) || { from: "/" }; const { loggedIn } = this.props; return loggedIn ? ( diff --git a/frontend/src/Auth/Login.tsx b/frontend/src/Auth/Login.tsx index 3992c77..6301384 100644 --- a/frontend/src/Auth/Login.tsx +++ b/frontend/src/Auth/Login.tsx @@ -10,7 +10,7 @@ import { IAppState } from "~redux/reducers"; interface ILoginComponentProps extends RouteComponentProps { inProgress: boolean; - error: string; + error: string | null; spinner: boolean; login: (username: string, password: string) => void; } diff --git a/frontend/src/Auth/Signup.tsx b/frontend/src/Auth/Signup.tsx index b084ce2..45f28ec 100644 --- a/frontend/src/Auth/Signup.tsx +++ b/frontend/src/Auth/Signup.tsx @@ -10,7 +10,7 @@ import { IAppState } from "~redux/reducers"; interface ISignupComponentProps extends RouteComponentProps { inProgress: boolean; - error: string; + error: string | null; spinner: boolean; signup: (username: string, password: string, email: string) => void; } diff --git a/frontend/src/Photos/Photos.scss b/frontend/src/Photos/Photos.scss index 96f54f0..9e7a8de 100644 --- a/frontend/src/Photos/Photos.scss +++ b/frontend/src/Photos/Photos.scss @@ -6,5 +6,6 @@ } .bp3-dark { - #overview {} -} \ No newline at end of file + #overview { + } +} diff --git a/frontend/src/redux/reducers.ts b/frontend/src/redux/reducers.ts index 35ea9b3..be3a9fe 100644 --- a/frontend/src/redux/reducers.ts +++ b/frontend/src/redux/reducers.ts @@ -27,10 +27,10 @@ const localSettingsPersistConfig = { }; export const rootReducer = combineReducers({ - auth: persistReducer(authPersistConfig, authReducer), + auth: persistReducer(authPersistConfig, authReducer as any), user: userReducer, localSettings: persistReducer( localSettingsPersistConfig, - localSettingsReducer, + localSettingsReducer as any, ), }); diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 1c9d822..3cdbc7f 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -16,6 +16,7 @@ "allowSyntheticDefaultImports": true, "strictFunctionTypes": true, "strictNullChecks": true, + "skipLibCheck": true, "baseUrl": "./src", "paths": { "~*": [ diff --git a/package-lock.json b/package-lock.json index 6647c4e..ab10df4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -381,6 +381,11 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.5.tgz", "integrity": "sha512-jVFzDV6NTbrLMxm4xDSIW/gKnk8rQLF9wAzLWIOg+5nU6ACrIMndeBdXci0FGtqJbP9tQvm6V39eshc96TO2wQ==" }, + "@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/prettier": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.1.1.tgz", @@ -1052,6 +1057,11 @@ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + }, "clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -1315,6 +1325,11 @@ "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==" }, + "compare-versions": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", + "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==" + }, "component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", @@ -1444,6 +1459,36 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "cosmiconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", + "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "dependencies": { + "parse-json": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", + "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "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==" + } + } + }, "cross-env": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.2.tgz", @@ -2072,6 +2117,14 @@ "locate-path": "^2.0.0" } }, + "find-versions": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz", + "integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==", + "requires": { + "semver-regex": "^2.0.0" + } + }, "flat": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", @@ -2366,6 +2419,76 @@ "resolved": "https://registry.npmjs.org/humanize-number/-/humanize-number-0.0.2.tgz", "integrity": "sha1-EcCvakcWQ2M1iFiASPF5lUFInBg=" }, + "husky": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.0.tgz", + "integrity": "sha512-tTMeLCLqSBqnflBZnlVDhpaIMucSGaYyX6855jM4AguGeWCeSzNdb1mfyWduTZ3pe3SJVvVWGL0jO1iKZVPfTA==", + "requires": { + "chalk": "^4.0.0", + "ci-info": "^2.0.0", + "compare-versions": "^3.6.0", + "cosmiconfig": "^7.0.0", + "find-versions": "^3.2.0", + "opencollective-postinstall": "^2.0.2", + "pkg-dir": "^4.2.0", + "please-upgrade-node": "^3.2.0", + "slash": "^3.0.0", + "which-pm-runs": "^1.0.0" + }, + "dependencies": { + "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" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.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" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "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" + } + } + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -2635,6 +2758,11 @@ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -2886,6 +3014,11 @@ "type-check": "~0.4.0" } }, + "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": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", @@ -3581,6 +3714,11 @@ "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz", "integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q=" }, + "opencollective-postinstall": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==" + }, "optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -3778,6 +3916,14 @@ "find-up": "^2.1.0" } }, + "please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "requires": { + "semver-compare": "^1.0.0" + } + }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -4349,6 +4495,16 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=" + }, + "semver-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz", + "integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==" + }, "serialize-javascript": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", @@ -5041,6 +5197,11 @@ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, + "which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=" + }, "wide-align": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", @@ -5150,6 +5311,11 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, + "yaml": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz", + "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==" + }, "yargonaut": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/yargonaut/-/yargonaut-1.1.4.tgz", diff --git a/package.json b/package.json index b596db8..d54cb6e 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,16 @@ "ts-node-dev": "ts-node-dev -r tsconfig-paths/register ./src/server.ts", "dev": "cross-env NODE_ENV=development concurrently npm:ts-node-dev npm:start-frontend -c 'blue,green'", "test": "cross-env NODE_ENV=test mocha --timeout 15000 -r ts-node/register -r tsconfig-paths/register 'src/tests/**/*.ts' ", - "lint": "eslint ./src/** --ext .js,.jsx,.ts,.tsx", + "test-frontend": "cd frontend && npm test", + "test-all": "npm test && npm run test-frontend", + "lint": "eslint ./src/** --ext .js,.jsx,.ts,.tsx && tsc --noEmit", + "lint-fix": "eslint ./src/** --ext .js,.jsx,.ts,.tsx --fix", "lint-frontend": "cd frontend && npm run lint", - "lint-all": "npm run lint && npm run lint-frontend" + "lint-frontend-fix": "cd frontend && npm run lint-fix", + "lint-all": "npm run lint && npm run lint-frontend", + "lint-all-fix": "npm run lint-fix && npm run lint-frontend-fix", + "prettier-check": "prettier src/** --check && prettier frontend/src/** --check", + "prettify": "prettier src/** --write && prettier frontend/src/** --write" }, "license": "MIT", "dependencies": { @@ -26,6 +33,7 @@ "eslint-plugin-import": "^2.22.1", "eslint-plugin-mocha": "^8.0.0", "eslint-plugin-prettier": "^3.1.4", + "husky": "^4.3.0", "jsonwebtoken": "^8.5.1", "koa": "^2.13.0", "koa-body": "^4.2.0", @@ -63,5 +71,10 @@ "@types/mocha": "^8.0.3", "@types/prettier": "^2.1.1", "@types/supertest": "^2.0.10" + }, + "husky": { + "hooks": { + "pre-commit": "npm run lint-all && npm run prettier-check" + } } -} +} \ No newline at end of file diff --git a/src/tests/.eslintrc.json b/src/tests/.eslintrc.json index 59d58e2..e9a88cc 100644 --- a/src/tests/.eslintrc.json +++ b/src/tests/.eslintrc.json @@ -1,8 +1,4 @@ { - "plugins": [ - "mocha" - ], - "extends": [ - "plugin:mocha/recommended" - ] -} \ No newline at end of file + "plugins": ["mocha"], + "extends": ["plugin:mocha/recommended"] +} diff --git a/tsconfig.json b/tsconfig.json index 16ecd64..2d7f07d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,6 +13,7 @@ "noImplicitAny": true, "strictFunctionTypes": true, "strictNullChecks": true, + "skipLibCheck": true, "baseUrl": "./src", "paths": { "~*": [