From c4df1785e31eb1a4a0a98a81c818c7a7af4b05c0 Mon Sep 17 00:00:00 2001 From: Freek Mencke Date: Thu, 16 May 2019 19:03:06 +0200 Subject: [PATCH 1/2] Updated dependencies and webpack, improved project structure, created logging middleware --- .dockerignore | 9 + .gitignore | 3 +- package-lock.json | 464 +++++++++++++----- package.json | 50 +- src/app/app.ts | 8 +- ...le-system-util.ts => file-system-utils.ts} | 6 +- src/app/common/sql-utils.ts | 54 ++ src/app/middleware/logger.middleware.ts | 7 + src/app/routes/health.router-factory.ts | 4 +- src/app/routes/item.router-factory.ts | 9 +- src/app/routes/news.router-factory.ts | 15 +- src/app/routes/player.router-factory.ts | 9 +- src/app/routes/xp.router.ts | 16 +- src/config/api.ts | 63 --- src/config/config.dev.ts | 16 + src/config/config.interface.ts | 1 + src/config/config.ts | 9 +- src/main.ts | 6 +- tsconfig.json | 4 +- webpack.config.js | 21 +- 20 files changed, 490 insertions(+), 284 deletions(-) create mode 100644 .dockerignore rename src/app/common/{file-system-util.ts => file-system-utils.ts} (80%) create mode 100644 src/app/common/sql-utils.ts create mode 100644 src/app/middleware/logger.middleware.ts delete mode 100644 src/config/api.ts create mode 100644 src/config/config.dev.ts diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..e134473 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,9 @@ +dist +node_modules +scripts +.editorconfig +.gitignore +.travis.yml +Dockerfile +LICENSE +README.md diff --git a/.gitignore b/.gitignore index f77c418..1e93bb1 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ node_modules yarn-error.log **/*.hidden.* -dist \ No newline at end of file +**/secrets/** +dist diff --git a/package-lock.json b/package-lock.json index 2d246ff..40c77ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53,14 +53,20 @@ } }, "@types/cors": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.4.tgz", - "integrity": "sha512-ipZjBVsm2tF/n8qFGOuGBkUij9X9ZswVi9G3bx/6dz7POpVa6gVHcj1wsX/LVEn9MMF41fxK/PnZPPoTD1UFPw==", + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-GmK8AKu8i+s+EChK/uZ5IbrXPcPaQKWaNSGevDT/7o3gFObwSUQwqb1jMqxuo+YPvj0ckGzINI+EO7EHcmJjKg==", "dev": true, "requires": { "@types/express": "*" } }, + "@types/events": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", + "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", + "dev": true + }, "@types/express": { "version": "4.16.1", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.16.1.tgz", @@ -82,6 +88,17 @@ "@types/range-parser": "*" } }, + "@types/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", + "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "dev": true, + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, "@types/helmet": { "version": "0.0.43", "resolved": "https://registry.npmjs.org/@types/helmet/-/helmet-0.0.43.tgz", @@ -97,6 +114,12 @@ "integrity": "sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw==", "dev": true }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, "@types/mysql": { "version": "2.15.6", "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.6.tgz", @@ -107,15 +130,15 @@ } }, "@types/node": { - "version": "10.12.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.10.tgz", - "integrity": "sha512-8xZEYckCbUVgK8Eg7lf5Iy4COKJ5uXlnIOnePN0WUwSQggy9tolM+tDJf7wMOnT/JT/W9xDYIaYggt3mRV2O5w==", + "version": "10.14.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.6.tgz", + "integrity": "sha512-Fvm24+u85lGmV4hT5G++aht2C5I4Z4dYlWZIh62FAfFO/TfzXtPpoLI6I7AuBWkIFqZCnhFOoTT7RjjaIL5Fjg==", "dev": true }, "@types/node-fetch": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.3.2.tgz", - "integrity": "sha512-yW0EOebSsQme9yKu09XbdDfle4/SmWZMK4dfteWcSLCYNQQcF+YOv0kIrvm+9pO11/ghA4E6A+RNQqvYj4Nr3A==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.3.4.tgz", + "integrity": "sha512-ZwGXz5osL88SF+jlbbz0WJlINlOZHoSWPrLytQRWRdB6j/KVLup1OoqIxnjO6q9ToqEEP3MZFzJCotgge+IiRw==", "dev": true, "requires": { "@types/node": "*" @@ -498,11 +521,12 @@ } }, "assert": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", "dev": true, "requires": { + "object-assign": "^4.1.1", "util": "0.10.3" }, "dependencies": { @@ -656,20 +680,71 @@ "dev": true }, "body-parser": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", - "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", "requires": { - "bytes": "3.0.0", + "bytes": "3.1.0", "content-type": "~1.0.4", "debug": "2.6.9", "depd": "~1.1.2", - "http-errors": "~1.6.3", - "iconv-lite": "0.4.23", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", "on-finished": "~2.3.0", - "qs": "6.5.2", - "raw-body": "2.3.3", - "type-is": "~1.6.16" + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "dependencies": { + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "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" + } + }, + "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==" + }, + "mime-types": { + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "requires": { + "mime-db": "1.40.0" + } + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + } } }, "boxen": { @@ -1008,9 +1083,9 @@ } }, "clean-webpack-plugin": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-2.0.1.tgz", - "integrity": "sha512-vway5pXGVd91bicwjaf8j188Al6VMf9R9Ekl6q0qeiaWStRsOOXuh4qtjX1UrUvmz5XevQVCdjBuzr4Tzsnpog==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-2.0.2.tgz", + "integrity": "sha512-pi1111o4OBd9qvacbgs+NRqClfVPKVIc66B4d8kx6Ho/L+i9entQ/NpK600CsTYTPu3kWvKwwyKarsYMvC2xeA==", "dev": true, "requires": { "del": "^4.0.0" @@ -1384,17 +1459,18 @@ } }, "del": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-4.0.0.tgz", - "integrity": "sha512-/BnSJ+SuZyLu7xMn48kZY0nMXDi+5KNmR4g8n21Wivsl8+B9njV6/5kcTNE9juSprp0zRWBU28JuHUq0FqK1Nw==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", "dev": true, "requires": { + "@types/glob": "^7.1.1", "globby": "^6.1.0", "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.2" + "rimraf": "^2.6.3" } }, "depd": { @@ -1708,9 +1784,9 @@ } }, "expect-ct": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/expect-ct/-/expect-ct-0.1.1.tgz", - "integrity": "sha512-ngXzTfoRGG7fYens3/RMb6yYoVLvLMfmsSllP/mZPxNHgFq41TmPSLF/nLY7fwoclI2vElvAmILFWGUYqdjfCg==" + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/expect-ct/-/expect-ct-0.2.0.tgz", + "integrity": "sha512-6SK3MG/Bbhm8MsgyJAylg+ucIOU71/FzyFalcfu5nY19dH8y/z0tBJU0wrNBXD4B27EoQtqPF/9wqH0iYAd04g==" }, "express": { "version": "4.16.4", @@ -1749,6 +1825,42 @@ "vary": "~1.1.2" }, "dependencies": { + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, "statuses": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", @@ -1855,9 +1967,9 @@ "dev": true }, "feature-policy": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/feature-policy/-/feature-policy-0.2.0.tgz", - "integrity": "sha512-2hGrlv6efG4hscYVZeaYjpzpT6I2OZgYqE2yDUzeAcKj2D1SH0AsEzqJNXzdoglEddcIXQQYop3lD97XpG75Jw==" + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/feature-policy/-/feature-policy-0.3.0.tgz", + "integrity": "sha512-ZtijOTFN7TzCujt1fnNhfWPFPSHeZkesff9AXZj+UEjYBynWNUIYpC87Ve4wHzyexQsImicLu7WsC2LHq7/xrQ==" }, "figgy-pudding": { "version": "3.5.1", @@ -2001,9 +2113,9 @@ } }, "frameguard": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/frameguard/-/frameguard-3.0.0.tgz", - "integrity": "sha1-e8rUae57lukdEs6zlZx4I1qScuk=" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/frameguard/-/frameguard-3.1.0.tgz", + "integrity": "sha512-TxgSKM+7LTA6sidjOiSZK9wxY0ffMPY3Wta//MqwmX0nZuEHc8QrkV8Fh3ZhMJeiH+Uyh/tcaarImRy8u77O7g==" }, "fresh": { "version": "0.5.2", @@ -2079,14 +2191,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2101,20 +2211,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -2231,8 +2338,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -2244,7 +2350,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -2259,7 +2364,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -2267,14 +2371,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -2293,7 +2395,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -2374,8 +2475,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -2387,7 +2487,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -2509,7 +2608,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -2782,24 +2880,24 @@ } }, "helmet": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/helmet/-/helmet-3.16.0.tgz", - "integrity": "sha512-rsTKRogc5OYGlvSHuq5QsmOsOzF6uDoMqpfh+Np8r23+QxDq+SUx90Rf8HyIKQVl7H6NswZEwfcykinbAeZ6UQ==", + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-3.18.0.tgz", + "integrity": "sha512-TsKlGE5UVkV0NiQ4PllV9EVfZklPjyzcMEMjWlyI/8S6epqgRT+4s4GHVgc25x0TixsKvp3L7c91HQQt5l0+QA==", "requires": { "depd": "2.0.0", "dns-prefetch-control": "0.1.0", "dont-sniff-mimetype": "1.0.0", - "expect-ct": "0.1.1", - "feature-policy": "0.2.0", - "frameguard": "3.0.0", + "expect-ct": "0.2.0", + "feature-policy": "0.3.0", + "frameguard": "3.1.0", "helmet-crossdomain": "0.3.0", "helmet-csp": "2.7.1", "hide-powered-by": "1.0.0", "hpkp": "2.0.0", "hsts": "2.2.0", "ienoopen": "1.1.0", - "nocache": "2.0.0", - "referrer-policy": "1.1.0", + "nocache": "2.1.0", + "referrer-policy": "1.2.0", "x-xss-protection": "1.1.0" }, "dependencies": { @@ -2895,9 +2993,9 @@ "dev": true }, "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "requires": { "safer-buffer": ">= 2.1.2 < 3" } @@ -3144,18 +3242,29 @@ "dev": true }, "is-path-cwd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.0.0.tgz", - "integrity": "sha512-m5dHHzpOXEiv18JEORttBO64UgTEypx99vCxQLjbBvGhOJxnTNglYoFXxwo6AbsQb79sqqycQEHv2hWkHZAijA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.1.0.tgz", + "integrity": "sha512-Sc5j3/YnM8tDeyCsVeKlm/0p95075DyLmDEIkSgQ7mXkrOX+uTCtmQFm0CYzVyJwcCCmO3k8qfJt17SxQwB5Zw==", "dev": true }, "is-path-in-cwd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.0.0.tgz", - "integrity": "sha512-6Vz5Gc9s/sDA3JBVu0FzWufm8xaBsqy1zn8Q6gmvGP6nSDMw78aS4poBNeatWjaRpTpxxLn1WOndAiOlk+qY8A==", + "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==", "dev": true, "requires": { - "is-path-inside": "^1.0.0" + "is-path-inside": "^2.1.0" + }, + "dependencies": { + "is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "dev": true, + "requires": { + "path-is-inside": "^1.0.2" + } + } } }, "is-path-inside": { @@ -3200,6 +3309,12 @@ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -3621,9 +3736,9 @@ "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" }, "neo-async": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", - "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", + "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", "dev": true }, "nice-try": { @@ -3633,14 +3748,14 @@ "dev": true }, "nocache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.0.0.tgz", - "integrity": "sha1-ICtIAhoMTL3i34DeFaF0Q8i0OYA=" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.1.0.tgz", + "integrity": "sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q==" }, "node-fetch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.3.0.tgz", - "integrity": "sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA==" + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", + "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" }, "node-libs-browser": { "version": "2.2.0", @@ -3931,15 +4046,15 @@ } }, "p-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.0.0.tgz", - "integrity": "sha512-GO107XdrSUmtHxVoi60qc9tUl/KkNKm+X2CF4P9amalpGxv5YqVPJNfSb0wcA+syCopkZvYYIzW8OVTQW59x/w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", "dev": true }, "p-try": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.1.0.tgz", - "integrity": "sha512-H2RyIJ7+A3rjkwKC2l5GGtU4H1vkxKCAGsWasNVd0Set+6i4znxbWy6/j16YDPJDWxhsgZiKAstMEP8wCdSpjA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, "package-json": { @@ -4062,6 +4177,12 @@ "sha.js": "^2.4.8" } }, + "picomatch": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.0.7.tgz", + "integrity": "sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==", + "dev": true + }, "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -4254,14 +4375,38 @@ "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" }, "raw-body": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "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" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + } } }, "rc": { @@ -4302,9 +4447,9 @@ } }, "referrer-policy": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.1.0.tgz", - "integrity": "sha1-NXdOtzW/UPtsB46DM0tHI1AgfXk=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.2.0.tgz", + "integrity": "sha512-LgQJIuS6nAy1Jd88DCQRemyE3mS+ispwlqMk3b0yjZ257fI1v9c+/p6SD5gP5FGyXUIgrNOAfmyioHwZtYv2VA==" }, "regex-not": { "version": "1.0.2", @@ -4512,9 +4657,9 @@ } }, "serialize-javascript": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.6.1.tgz", - "integrity": "sha512-A5MOagrPFga4YaKQSWHryl7AXvbQkEqpw4NNYMTNYUNV51bA8ABHgYFpqKx+YFFrw59xMV1qGH1R4AgoNIVgCw==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz", + "integrity": "sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA==", "dev": true }, "serve-static": { @@ -4732,9 +4877,9 @@ } }, "source-map-support": { - "version": "0.5.11", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.11.tgz", - "integrity": "sha512-//sajEx/fGL3iw6fltKMdPvy8kL3kJ2O3iuYlRoT3k9Kb4BjOoZ+BZzaNHeuaruSt+Kf3Zk9tnfAQg9/AJqUVQ==", + "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==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -4932,19 +5077,20 @@ } }, "terser-webpack-plugin": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.2.3.tgz", - "integrity": "sha512-GOK7q85oAb/5kE12fMuLdn2btOS9OBZn4VsecpHDywoUC/jLhSAKOiYo0ezx7ss2EXPMzyEWFoE0s1WLE+4+oA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.2.4.tgz", + "integrity": "sha512-64IiILNQlACWZLzFlpzNaG0bpQ4ytaB7fwOsbpsdIV70AfLUmIGGeuKL0YV2WmtcrURjE2aOvHD4/lrFV3Rg+Q==", "dev": true, "requires": { - "cacache": "^11.0.2", + "cacache": "^11.3.2", "find-cache-dir": "^2.0.0", + "is-wsl": "^1.1.0", "schema-utils": "^1.0.0", - "serialize-javascript": "^1.4.0", + "serialize-javascript": "^1.7.0", "source-map": "^0.6.1", - "terser": "^3.16.1", - "webpack-sources": "^1.1.0", - "worker-farm": "^1.5.2" + "terser": "^3.17.0", + "webpack-sources": "^1.3.0", + "worker-farm": "^1.7.0" }, "dependencies": { "source-map": { @@ -5028,6 +5174,11 @@ "repeat-string": "^1.6.1" } }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, "touch": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", @@ -5044,16 +5195,67 @@ "dev": true }, "ts-loader": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.4.3.tgz", - "integrity": "sha512-pHwZFkZioL7Yi2su0bhW2/djxZ+0iGat1cxlAif4Eg9j5znVYuWGtW0YYY/5w8W+IzLcAlD5KwJDrs5unUKIRA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-6.0.0.tgz", + "integrity": "sha512-lszy+D41R0Te2+loZxADWS+E1+Z55A+i3dFfFie1AZHL++65JRKVDBPQgeWgRrlv5tbxdU3zOtXp8b7AFR6KEg==", "dev": true, "requires": { "chalk": "^2.3.0", "enhanced-resolve": "^4.0.0", "loader-utils": "^1.0.2", - "micromatch": "^3.1.4", - "semver": "^5.0.1" + "micromatch": "^4.0.0", + "semver": "^6.0.0" + }, + "dependencies": { + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "semver": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", + "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + } } }, "tslib": { @@ -5361,9 +5563,9 @@ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "v8-compile-cache": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz", - "integrity": "sha512-1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz", + "integrity": "sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w==", "dev": true }, "vary": { @@ -5392,9 +5594,9 @@ } }, "webpack": { - "version": "4.30.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.30.0.tgz", - "integrity": "sha512-4hgvO2YbAFUhyTdlR4FNyt2+YaYBYHavyzjCMbZzgglo02rlKi/pcsEzwCuCpsn1ryzIl1cq/u8ArIKu8JBYMg==", + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.31.0.tgz", + "integrity": "sha512-n6RVO3X0LbbipoE62akME9K/JI7qYrwwufs20VvgNNpqUoH4860KkaxJTbGq5bgkVZF9FqyyTG/0WPLH3PVNJA==", "dev": true, "requires": { "@webassemblyjs/ast": "1.8.5", @@ -5445,9 +5647,9 @@ } }, "webpack-cli": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.1.tgz", - "integrity": "sha512-c2inFU7SM0IttEgF7fK6AaUsbBnORRzminvbyRKS+NlbQHVZdCtzKBlavRL5359bFsywXGRAItA5di/IruC8mg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.2.tgz", + "integrity": "sha512-FLkobnaJJ+03j5eplxlI0TUxhGCOdfewspIGuvDVtpOlrAuKMFC57K42Ukxqs1tn8947/PM6tP95gQc0DCzRYA==", "dev": true, "requires": { "chalk": "^2.4.1", @@ -5521,9 +5723,9 @@ } }, "worker-farm": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz", - "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", "dev": true, "requires": { "errno": "~0.1.7" diff --git a/package.json b/package.json index 24f0046..0048e36 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osrs-tracker-api", - "version": "0.1.3", + "version": "0.2.0", "private": true, "author": "Freek Mencke", "homepage": "https://twitter.com/FreekMencke", @@ -9,43 +9,43 @@ "url": "https://github.com/osrs-tracker/osrs-tracker-api" }, "scripts": { - "start": "webpack --watch --config webpack.config.js --progress --env.mode=development && node dist/osrs-tracker-api.js", - "start:prod": "webpack --watch --config webpack.config.js --progress --env.mode=production && node dist/osrs-tracker-api.js", - "build:prod": "webpack --config webpack.config.js --progress --env.mode=production", - "build:ci": "webpack --config webpack.config.js --env.mode=production", + "start": "webpack --progress --env.development --env.nodemon", + "start:prod": "webpack --progress --env.nodemon", + "build:prod": "webpack --progress", + "build:ci": "webpack", "build:docker": "docker build --rm -t toxsickcoder/osrs-tracker-api:dev .", "deploy:docker": "sh ./scripts/deploy.sh", - "analyse:dev": "webpack --config webpack.config.js --progress --env.mode=development --env.analyse && start dist/report.html", - "analyse:prod": "webpack --config webpack.config.js --progress --env.mode=production --env.analyse && start dist/report.html", + "analyse:dev": "webpack --progress --env.development --env.analyse && start dist/report.html", + "analyse:prod": "webpack --progress --env.analyse && start dist/report.html", "lint": "tslint --project ." }, "dependencies": { - "body-parser": "1.18.3", + "body-parser": "1.19.0", "compression": "1.7.4", "cors": "2.8.5", "express": "4.16.4", - "helmet": "3.16.0", + "helmet": "3.18.0", "mysql": "2.17.1", - "node-fetch": "2.3.0" + "node-fetch": "2.6.0" }, "devDependencies": { - "@types/body-parser": "1.17.0", - "@types/compression": "0.0.36", - "@types/cors": "2.8.4", - "@types/express": "4.16.1", - "@types/helmet": "0.0.43", - "@types/mysql": "2.15.6", - "@types/node": "^10.0.0", - "@types/node-fetch": "2.3.2", - "clean-webpack-plugin": "2.0.1", - "nodemon-webpack-plugin": "4.0.8", - "terser-webpack-plugin": "1.2.3", - "ts-loader": "5.4.3", + "@types/body-parser": "^1.17.0", + "@types/compression": "^0.0.36", + "@types/cors": "^2.8.5", + "@types/express": "^4.16.1", + "@types/helmet": "^0.0.43", + "@types/mysql": "^2.15.6", + "@types/node": "^10.14.6", + "@types/node-fetch": "^2.3.4", + "clean-webpack-plugin": "^2.0.2", + "nodemon-webpack-plugin": "^4.0.8", + "terser-webpack-plugin": "^1.2.4", + "ts-loader": "^6.0.0", "tslint": "^5.16.0", "tslint-eslint-rules": "^5.4.0", "typescript": "^3.4.5", - "webpack": "^4.30.0", - "webpack-bundle-analyzer": "3.3.2", - "webpack-cli": "3.3.1" + "webpack": "^4.31.0", + "webpack-bundle-analyzer": "^3.3.2", + "webpack-cli": "^3.3.2" } } diff --git a/src/app/app.ts b/src/app/app.ts index d12195f..17ce0b7 100644 --- a/src/app/app.ts +++ b/src/app/app.ts @@ -4,8 +4,9 @@ import compression from 'compression'; import cors from 'cors'; import express, { Application } from 'express'; import helmet from 'helmet'; -import { API } from '../config/api'; +import { config } from '../config/config'; import { Logger } from './common/logger'; +import { requestLogger } from './middleware/logger.middleware'; import { HealthRouterFactory } from './routes/health.router-factory'; import { IconRouter } from './routes/icon.router-factory'; import { ItemRouter } from './routes/item.router-factory'; @@ -25,8 +26,8 @@ export class App { } start(worker: Worker): void { - this._app.listen(API.CONFIG.PORT, () => { - Logger.log(`WORKER ${worker.id} CREATED ON PORT ${API.CONFIG.PORT}`); + this._app.listen(config.port, () => { + Logger.log(`WORKER ${worker.id} CREATED ON PORT ${config.port}`); this.setupRouters(); }); } @@ -37,6 +38,7 @@ export class App { this._app.use(cors()); this._app.use(bodyParser.urlencoded({ extended: true })); this._app.use(bodyParser.json()); + this._app.use(requestLogger()); } private setupRouters(): void { diff --git a/src/app/common/file-system-util.ts b/src/app/common/file-system-utils.ts similarity index 80% rename from src/app/common/file-system-util.ts rename to src/app/common/file-system-utils.ts index 0294789..f00f3b6 100644 --- a/src/app/common/file-system-util.ts +++ b/src/app/common/file-system-utils.ts @@ -1,9 +1,8 @@ +import { exists, mkdir } from 'fs'; import { join } from 'path'; -import { mkdir, exists } from 'fs'; import { Logger } from './logger'; -export class FileSystemUtil { - +export class FileSystemUtils { static createIconsFolderIfMissing(): void { const iconsPath = join(__dirname, '/icons/'); @@ -11,5 +10,4 @@ export class FileSystemUtil { if (!exists) mkdir(iconsPath, () => Logger.log('CREATED ICONS FOLDER')); }); } - } diff --git a/src/app/common/sql-utils.ts b/src/app/common/sql-utils.ts new file mode 100644 index 0000000..f02afbc --- /dev/null +++ b/src/app/common/sql-utils.ts @@ -0,0 +1,54 @@ +import { createPool, PoolConnection } from 'mysql'; +import { config } from '../../config/config'; +import { Logger } from './logger'; + +export class SqlUtils { + private static readonly DB_POOL = createPool({ + ...config.poolConfig, + connectionLimit: 20, + timezone: 'Z', + }); + + private static setupDbConnection(): Promise { + return new Promise((resolve, reject) => { + const MAX_RETRY_COUNT = 3; + let retryCount = 0; + + const getConnection = () => + this.DB_POOL.getConnection((err, connection) => { + retryCount++; + + if (retryCount < MAX_RETRY_COUNT && (err || !connection)) { + Logger.log('FAILED TO CONNECT WITH DATABASE - RETRYING IN 1 SECOND.', err); + setTimeout(() => getConnection(), 1000); + } else if (retryCount >= MAX_RETRY_COUNT) { + reject(); + } else resolve(connection); + }); + getConnection(); + }); + } + + static async getDbConnection(dbConnectionLogic: (connection: PoolConnection) => Promise): Promise { + let connection: PoolConnection | null = null; + try { + connection = await SqlUtils.setupDbConnection(); + } catch (e) { + Logger.log('FAILED TO SETUP DATABASE CONNECTION.', e); + } + + if (!connection) return; + + try { + await dbConnectionLogic(connection); + } catch (e) { + Logger.log('UNEXPECTED ERROR OCCURED.', e); + } + + try { + connection.release(); + } catch (e) { + Logger.log('FAILED TO RELEASE CONNECTION, COULD BE RELEASED ALREADY.', e); + } + } +} diff --git a/src/app/middleware/logger.middleware.ts b/src/app/middleware/logger.middleware.ts new file mode 100644 index 0000000..180127b --- /dev/null +++ b/src/app/middleware/logger.middleware.ts @@ -0,0 +1,7 @@ +import { NextFunction, Request, RequestHandler, Response } from 'express'; +import { Logger } from '../common/logger'; + +export const requestLogger = (): RequestHandler => (req: Request, res: Response, next: NextFunction) => { + next(); + Logger.log(res.statusCode, req.method, req.originalUrl); +}; diff --git a/src/app/routes/health.router-factory.ts b/src/app/routes/health.router-factory.ts index 4a75fa4..87be4f5 100644 --- a/src/app/routes/health.router-factory.ts +++ b/src/app/routes/health.router-factory.ts @@ -1,5 +1,5 @@ import { Application, Router } from 'express'; -import { API } from '../../config/api'; +import { SqlUtils } from '../common/sql-utils'; import { HealthRepository } from '../repositories/health.repository'; import { RouterFactory } from './router.interface'; @@ -15,7 +15,7 @@ export class HealthRouterFactory implements RouterFactory { private healthcheck(router: Router): void { router.get('/', async (req, res) => { try { - await API.getDbConnection(connection => + await SqlUtils.getDbConnection(connection => HealthRepository.checkConnection(connection).then(result => res.status(result.success ? 200 : 500).send(result.success ? 'HEALTHY' : 'UNHEALTHY') ) diff --git a/src/app/routes/item.router-factory.ts b/src/app/routes/item.router-factory.ts index feece87..b34ce33 100644 --- a/src/app/routes/item.router-factory.ts +++ b/src/app/routes/item.router-factory.ts @@ -1,6 +1,5 @@ import { Application, Router } from 'express'; -import { API } from '../../config/api'; -import { Logger } from '../common/logger'; +import { SqlUtils } from '../common/sql-utils'; import { ItemRepository } from '../repositories/item.repository'; import { RouterFactory } from './router.interface'; @@ -16,9 +15,8 @@ export class ItemRouter implements RouterFactory { private getItem(router: Router): void { router.get('/:id', (req, res) => { - API.getDbConnection(connection => + SqlUtils.getDbConnection(connection => ItemRepository.getItem(req.params.id, connection).then(({ statusCode, items }) => { - Logger.log(statusCode, 'GET /item/:id', { id: req.params.id, itemName: items && items[0].name }); res.status(statusCode); res.send(items); }) @@ -28,9 +26,8 @@ export class ItemRouter implements RouterFactory { private getItems(router: Router): void { router.get('/', (req, res) => { - API.getDbConnection(connection => + SqlUtils.getDbConnection(connection => ItemRepository.getItems(req.query.query, connection).then(({ statusCode, items }) => { - Logger.log(statusCode, 'GET /item', { query: req.query.query, results: (items && items.length) || 0 }); res.status(statusCode); res.send(items); }) diff --git a/src/app/routes/news.router-factory.ts b/src/app/routes/news.router-factory.ts index ce55ac5..93d1726 100644 --- a/src/app/routes/news.router-factory.ts +++ b/src/app/routes/news.router-factory.ts @@ -1,6 +1,5 @@ import { Application, Router } from 'express'; -import { API } from '../../config/api'; -import { Logger } from '../common/logger'; +import { SqlUtils } from '../common/sql-utils'; import { NewsRepository } from '../repositories/news.repository'; import { RouterFactory } from './router.interface'; @@ -18,9 +17,8 @@ export class NewsRouter implements RouterFactory { private getNewsPost(router: Router): void { router.get('/:id', (req, res) => { - API.getDbConnection(connection => + SqlUtils.getDbConnection(connection => NewsRepository.getNewsItem(req.params.id, req.query.uuid, connection).then(({ statusCode, newsPost }) => { - Logger.log(statusCode, 'GET /news/:id', { id: req.params.id, uuid: req.query.uuid }); res.status(statusCode); res.send(newsPost); }) @@ -30,9 +28,8 @@ export class NewsRouter implements RouterFactory { private getNewsPosts(router: Router): void { router.get('/', (req, res) => { - API.getDbConnection(connection => + SqlUtils.getDbConnection(connection => NewsRepository.getNewsItems(req.query.uuid, +req.query.offset, connection).then(({ statusCode, newsPosts }) => { - Logger.log(statusCode, 'GET /news', { uuid: req.query.uuid, offset: req.query.offset }); res.status(statusCode); res.send(newsPosts); }) @@ -42,9 +39,8 @@ export class NewsRouter implements RouterFactory { private upvote(router: Router): void { router.post('/upvote', (req, res) => { - API.getDbConnection(connection => + SqlUtils.getDbConnection(connection => NewsRepository.upvote(req.body.newsId, req.body.uuid, connection).then(({ statusCode }) => { - Logger.log(statusCode, 'POST /news/upvote', { id: req.body.newsId, uuid: req.body.uuid }); res.status(statusCode); res.send(); }) @@ -54,9 +50,8 @@ export class NewsRouter implements RouterFactory { private downvote(router: Router): void { router.post('/downvote', (req, res) => { - API.getDbConnection(connection => + SqlUtils.getDbConnection(connection => NewsRepository.downvote(req.body.newsId, req.body.uuid, connection).then(({ statusCode }) => { - Logger.log(statusCode, 'POST /news/downvote', { id: req.body.newsId, uuid: req.body.uuid }); res.status(statusCode); res.send(); }) diff --git a/src/app/routes/player.router-factory.ts b/src/app/routes/player.router-factory.ts index 9eab1da..b8ee29f 100644 --- a/src/app/routes/player.router-factory.ts +++ b/src/app/routes/player.router-factory.ts @@ -1,6 +1,5 @@ import { Application, Router } from 'express'; -import { API } from '../../config/api'; -import { Logger } from '../common/logger'; +import { SqlUtils } from '../common/sql-utils'; import { PlayerRepository } from '../repositories/player.repository'; import { RouterFactory } from './router.interface'; @@ -16,9 +15,8 @@ export class PlayerRouter implements RouterFactory { private getPlayer(router: Router): void { router.get('/:username', (req, res) => { - API.getDbConnection(connection => + SqlUtils.getDbConnection(connection => PlayerRepository.getPlayer(req.params.username, connection).then(({ statusCode, player }) => { - Logger.log(statusCode, 'GET /player/:username', { username: req.params.username }); res.status(statusCode); res.send(player); }) @@ -28,9 +26,8 @@ export class PlayerRouter implements RouterFactory { private insertPlayer(router: Router): void { router.post('/', (req, res) => { - API.getDbConnection(connection => + SqlUtils.getDbConnection(connection => PlayerRepository.insertPlayer(req.body, connection).then(({ statusCode }) => { - Logger.log(statusCode, 'POST /player', { player: req.body }); res.status(statusCode); res.send(); }) diff --git a/src/app/routes/xp.router.ts b/src/app/routes/xp.router.ts index c4c40ef..bf8cd28 100644 --- a/src/app/routes/xp.router.ts +++ b/src/app/routes/xp.router.ts @@ -1,6 +1,5 @@ import { Application, Router } from 'express'; -import { API } from '../../config/api'; -import { Logger } from '../common/logger'; +import { SqlUtils } from '../common/sql-utils'; import { XpRepository } from '../repositories/xp.repository'; import { RouterFactory } from './router.interface'; @@ -16,13 +15,9 @@ export class XpRouter implements RouterFactory { private insertInitialXpDatapoint(router: Router): void { router.post('/:username/initialDatapoint', (req, res) => { - API.getDbConnection(connection => + SqlUtils.getDbConnection(connection => XpRepository.insertInitialXpDatapoint(req.params.username, req.body.xpString, connection).then( ({ statusCode }) => { - Logger.log(statusCode, 'POST /xp/:username/initialDatapoint', { - username: req.params.username, - xpString: req.body.xpString, - }); res.status(statusCode); res.send(); } @@ -33,14 +28,9 @@ export class XpRouter implements RouterFactory { private getXpDatapointsForPlayer(router: Router): void { router.get('/:username/:period?', (req, res) => { - API.getDbConnection(connection => + SqlUtils.getDbConnection(connection => XpRepository.getXpDatapoints(req.params.username, +req.params.period, +req.query.offset, connection).then( ({ statusCode, xpDatapoints }) => { - Logger.log(statusCode, 'GET /xp/:username/:period?', { - username: req.params.username, - period: req.params.period, - offset: req.query.offset, - }); res.status(statusCode); res.send(xpDatapoints); } diff --git a/src/config/api.ts b/src/config/api.ts deleted file mode 100644 index 7e9dece..0000000 --- a/src/config/api.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { Response } from 'express'; -import { createPool, PoolConnection } from 'mysql'; -import { Logger } from '../app/common/logger'; -import { config } from './config'; - -export class API { - static readonly DB_POOL = createPool({ - ...config.poolConfig, - connectionLimit: 20, - timezone: 'Z', - }); - - static readonly CONFIG = { - VERSION: VERSION, - PORT: process.env.PORT || 8080, - }; - - private static setupDbConnection(): Promise { - return new Promise((resolve, reject) => { - const MAX_RETRY_COUNT = 3; - let retryCount = 0; - const getConnection = () => - this.DB_POOL.getConnection((err, connection) => { - retryCount++; - if (retryCount < MAX_RETRY_COUNT && (err || !connection)) { - Logger.log('FAILED TO CONNECT WITH DATABASE - RETRYING IN 1 SECOND.', err); - setTimeout(() => { - getConnection(); - }, 1000); - } else if (retryCount >= MAX_RETRY_COUNT) { - Logger.log('FAILED TO CONNECT WITH DATABASE.'); - reject(); - } else resolve(connection); - }); - getConnection(); - }); - } - - static getDbConnection( - dbConnectionLogic: (connection: PoolConnection) => Promise, - res?: Response - ): Promise { - return API.setupDbConnection() - .catch(() => { - if (res) res.sendStatus(503); - return null; - }) - .then((connection: PoolConnection | null) => { - if (!connection) return; - return dbConnectionLogic(connection) - .then(() => connection.release()) - .catch(err => { - Logger.log('UNEXPECTED ERROR OCCURED.', err); - try { - connection.release(); - } catch (e) { - /* Could be released already. */ - } - if (res) res.sendStatus(500); - }); - }); - } -} diff --git a/src/config/config.dev.ts b/src/config/config.dev.ts new file mode 100644 index 0000000..7436769 --- /dev/null +++ b/src/config/config.dev.ts @@ -0,0 +1,16 @@ +import { readFileSync } from 'fs'; +import { PoolConfig } from 'mysql'; +import { IConfig } from './config.interface'; + +const dbCredentials: PoolConfig = JSON.parse(readFileSync('src/config/secrets/db-osrs-tracker.json', 'utf8')); + +export const config: IConfig = { + port: Number(process.env.PORT) || 8080, + poolConfig: Object.assign(dbCredentials, { + ssl: { + ca: readFileSync('src/config/secrets/db-ca.pem'), + cert: readFileSync('src/config/secrets/db-client-cert.pem'), + key: readFileSync('src/config/secrets/db-client-key.pem'), + }, + }), +}; diff --git a/src/config/config.interface.ts b/src/config/config.interface.ts index 63e32aa..a050700 100644 --- a/src/config/config.interface.ts +++ b/src/config/config.interface.ts @@ -1,5 +1,6 @@ import { PoolConfig } from 'mysql'; export interface IConfig { + port: number; poolConfig: PoolConfig; } diff --git a/src/config/config.ts b/src/config/config.ts index c75a87d..ed1c854 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -1,15 +1,16 @@ -import { IConfig } from './config.interface'; import { readFileSync } from 'fs'; import { PoolConfig } from 'mysql'; +import { IConfig } from './config.interface'; const dbCredentials: PoolConfig = JSON.parse(readFileSync('/run/secrets/db-osrs-tracker.json', 'utf8')); export const config: IConfig = { + port: Number(process.env.PORT) || 8080, poolConfig: Object.assign(dbCredentials, { ssl: { ca: readFileSync('/run/secrets/db-ca.pem'), cert: readFileSync('/run/secrets/db-client-cert.pem'), - key: readFileSync('/run/secrets/db-client-key.pem') - } - }) + key: readFileSync('/run/secrets/db-client-key.pem'), + }, + }), }; diff --git a/src/main.ts b/src/main.ts index eecdede..8fffa6f 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,16 +1,16 @@ import cluster from 'cluster'; import os from 'os'; import { App } from './app/app'; -import { FileSystemUtil } from './app/common/file-system-util'; +import { FileSystemUtils } from './app/common/file-system-utils'; import { Logger } from './app/common/logger'; if (cluster.isMaster) { - FileSystemUtil.createIconsFolderIfMissing(); + FileSystemUtils.createIconsFolderIfMissing(); Logger.log('OSRS TRACKER API ACTIVE - FORKING WORKERS'); os.cpus().forEach(() => cluster.fork()); - cluster.on('exit', (worker: cluster.Worker) => { + cluster.on('exit', worker => { Logger.log(`WORKER ${worker.id} DIED - CREATING NEW WORKER`); cluster.fork(); }); diff --git a/tsconfig.json b/tsconfig.json index ebb450a..0e5fcb5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,12 +1,10 @@ { "compilerOptions": { - "target": "es2018", + "target": "esnext", "module": "esnext", "moduleResolution": "node", "lib": ["dom", "es2018"], "allowSyntheticDefaultImports": true, - "emitDecoratorMetadata": true, - "experimentalDecorators": true, "noUnusedLocals": true, "removeComments": true, "strict": true, diff --git a/webpack.config.js b/webpack.config.js index cd73fe9..05cb664 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,6 +1,5 @@ 'use strict'; -const path = require('path'); const webpack = require('webpack'); const CleanWebpackPlugin = require('clean-webpack-plugin'); const TerserPlugin = require('terser-webpack-plugin'); @@ -8,19 +7,18 @@ const NodemonPlugin = require('nodemon-webpack-plugin'); const packageJson = require('./package.json'); -module.exports = env => { +module.exports = (env = {}) => { const config = { entry: ['./src/main.ts'], - mode: env.mode, + mode: env.development ? 'development' : 'production', target: 'node', - devtool: env.mode === 'development' ? 'cheap-eval-source-map' : false, + devtool: env.development ? 'inline-source-map' : false, node: { __dirname: false, // Fix for native node __dirname __filename: false, // Fix for native node __filename }, output: { - filename: packageJson.name + '.js', - path: path.resolve(__dirname, 'dist'), + filename: `${packageJson.name}.js`, }, resolve: { extensions: ['.ts', '.js'], @@ -45,6 +43,7 @@ module.exports = env => { { test: /\.ts$/, use: 'ts-loader', + exclude: /node_modules/, }, ], }, @@ -52,16 +51,18 @@ module.exports = env => { new CleanWebpackPlugin(), new webpack.DefinePlugin({ VERSION: JSON.stringify(packageJson.version), - DEVELOP: env.mode === 'development', + DEVELOP: env.development, }), + // Use module replacement to use different configs for dev and prod new webpack.NormalModuleReplacementPlugin( - /config.ts/, - env.mode === 'production' ? 'config.ts' : 'config.hidden.ts' + /[\\/]src[\\/]config[\\/]config.ts$/, // [\\/] works on all operating systems. + env.development ? 'config.dev.ts' : 'config.ts' ), ], }; - if (env.mode === 'development') { + if (env.nodemon) { + config.watch = true; config.plugins.push(new NodemonPlugin()); } From 588a26b12d4abb1374cbb9e725016735b5ca4bd1 Mon Sep 17 00:00:00 2001 From: Freek Mencke Date: Thu, 16 May 2019 19:14:27 +0200 Subject: [PATCH 2/2] added blackist to filter out healthchecks for logging --- src/app/app.ts | 2 +- src/app/middleware/logger.middleware.ts | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/app/app.ts b/src/app/app.ts index 17ce0b7..b96c8f2 100644 --- a/src/app/app.ts +++ b/src/app/app.ts @@ -38,7 +38,7 @@ export class App { this._app.use(cors()); this._app.use(bodyParser.urlencoded({ extended: true })); this._app.use(bodyParser.json()); - this._app.use(requestLogger()); + this._app.use(requestLogger(['/health'])); } private setupRouters(): void { diff --git a/src/app/middleware/logger.middleware.ts b/src/app/middleware/logger.middleware.ts index 180127b..25fd6c8 100644 --- a/src/app/middleware/logger.middleware.ts +++ b/src/app/middleware/logger.middleware.ts @@ -1,7 +1,14 @@ import { NextFunction, Request, RequestHandler, Response } from 'express'; import { Logger } from '../common/logger'; -export const requestLogger = (): RequestHandler => (req: Request, res: Response, next: NextFunction) => { +export const requestLogger = (blacklist: string[] = []): RequestHandler => ( + req: Request, + res: Response, + next: NextFunction +) => { next(); + + if (blacklist.some(url => req.originalUrl.startsWith(url))) return; + Logger.log(res.statusCode, req.method, req.originalUrl); };