From c389b69a698c9f5b51e55f007325b4f36fcd0aaa Mon Sep 17 00:00:00 2001 From: timwekkenbc Date: Mon, 4 Nov 2024 14:17:17 -0800 Subject: [PATCH] Added winston logging, Added universal app logger, Updated existing logging to use this logger --- package-lock.json | 302 +++++++++++++++++- package.json | 4 +- src/api/decisions/decisions.service.spec.ts | 9 +- src/api/decisions/decisions.service.ts | 9 +- src/api/klamm/klamm.module.ts | 4 +- src/api/klamm/klamm.service.spec.ts | 3 +- src/api/klamm/klamm.service.ts | 41 +-- src/api/ruleData/ruleData.module.ts | 4 +- src/api/ruleData/ruleData.service.spec.ts | 2 + src/api/ruleData/ruleData.service.ts | 11 +- .../scenarioData/scenarioData.service.spec.ts | 2 + src/api/scenarioData/scenarioData.service.ts | 9 +- src/app.module.ts | 4 +- .../github-auth.controller.spec.ts | 2 + .../github-auth/github-auth.controller.ts | 7 +- src/auth/github-auth/github-auth.module.ts | 4 +- .../github-auth/github-auth.service.spec.ts | 3 +- src/auth/github-auth/github-auth.service.ts | 6 +- src/main.spec.ts | 2 +- src/main.ts | 15 +- src/utils/readFile.ts | 1 - src/winston-config.service.ts | 16 + 22 files changed, 403 insertions(+), 57 deletions(-) create mode 100644 src/winston-config.service.ts diff --git a/package-lock.json b/package-lock.json index 572f24b..285f024 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,8 +21,10 @@ "csv-parser": "^3.0.0", "mongoose": "^8.3.0", "multer": "^1.4.5-lts.1", + "nest-winston": "^1.9.7", "reflect-metadata": "^0.2.0", - "rxjs": "^7.8.1" + "rxjs": "^7.8.1", + "winston": "^3.16.0" }, "devDependencies": { "@nestjs/cli": "^10.0.0", @@ -924,6 +926,16 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@dabh/diagnostics": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", + "dependencies": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -2468,6 +2480,11 @@ "@types/superagent": "^8.1.0" } }, + "node_modules/@types/triple-beam": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==" + }, "node_modules/@types/validator": { "version": "13.11.10", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.10.tgz", @@ -2855,6 +2872,17 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -3066,6 +3094,11 @@ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", "dev": true }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==" + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -3207,7 +3240,6 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, "funding": [ { "type": "github", @@ -3682,6 +3714,15 @@ "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", "dev": true }, + "node_modules/color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "dependencies": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -3698,6 +3739,37 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/color/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/colorspace": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", + "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", + "dependencies": { + "color": "^3.1.3", + "text-hex": "1.0.x" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -4123,6 +4195,11 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "node_modules/enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" + }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -4465,11 +4542,18 @@ "node": ">= 0.6" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, "node_modules/events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, "engines": { "node": ">=0.8.x" } @@ -4664,6 +4748,11 @@ "bser": "2.1.1" } }, + "node_modules/fecha": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -4835,6 +4924,11 @@ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, + "node_modules/fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" + }, "node_modules/follow-redirects": { "version": "1.15.6", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", @@ -5282,7 +5376,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, "funding": [ { "type": "github", @@ -5509,7 +5602,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, "engines": { "node": ">=8" }, @@ -6421,6 +6513,11 @@ "node": ">=6" } }, + "node_modules/kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" + }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -6511,6 +6608,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/logform": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.1.tgz", + "integrity": "sha512-CdaO738xRapbKIMVn2m4F6KTj4j7ooJ8POVnebSgKo3KBz5axNXRAL7ZdRjIV6NOr2Uf4vjtRkxrFETOioCqSA==", + "dependencies": { + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/logform/node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -6900,6 +7021,18 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "node_modules/nest-winston": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/nest-winston/-/nest-winston-1.9.7.tgz", + "integrity": "sha512-pTTgImRgv7urojsDvaTlenAjyJNLj7ywamfjzrhWKhLhp80AKLYNwf103dVHeqZWe+nzp/vd9DGRs/UN/YadOQ==", + "dependencies": { + "fast-safe-stringify": "^2.1.1" + }, + "peerDependencies": { + "@nestjs/common": "^5.0.0 || ^6.6.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0", + "winston": "^3.0.0" + } + }, "node_modules/node-abort-controller": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", @@ -7003,6 +7136,14 @@ "wrappy": "1" } }, + "node_modules/one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "dependencies": { + "fn.name": "1.x.x" + } + }, "node_modules/onetime": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", @@ -7378,6 +7519,14 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -7799,6 +7948,14 @@ } ] }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -8085,6 +8242,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/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==" + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -8142,6 +8312,14 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", + "engines": { + "node": "*" + } + }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", @@ -8535,6 +8713,11 @@ "node": "*" } }, + "node_modules/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==" + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -8608,6 +8791,14 @@ "tree-kill": "cli.js" } }, + "node_modules/triple-beam": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", + "engines": { + "node": ">= 14.0.0" + } + }, "node_modules/ts-api-utils": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz", @@ -9115,6 +9306,107 @@ "node": ">= 8" } }, + "node_modules/winston": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.16.0.tgz", + "integrity": "sha512-xz7+cyGN5M+4CmmD4Npq1/4T+UZaz7HaeTlAruFUTjk79CNMq+P6H30vlE4z0qfqJ01VHYQwd7OZo03nYm/+lg==", + "dependencies": { + "@colors/colors": "^1.6.0", + "@dabh/diagnostics": "^2.0.2", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.6.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.7.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-transport": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.8.0.tgz", + "integrity": "sha512-qxSTKswC6llEMZKgCQdaWgDuMJQnhuvF5f2Nk3SNXc4byfQ+voo2mX1Px9dkNOuR8p0KAjfPG29PuYUSIb+vSA==", + "dependencies": { + "logform": "^2.6.1", + "readable-stream": "^4.5.2", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-transport/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/winston-transport/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/winston-transport/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/winston/node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/winston/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", diff --git a/package.json b/package.json index a8dd4be..428cb67 100644 --- a/package.json +++ b/package.json @@ -33,8 +33,10 @@ "csv-parser": "^3.0.0", "mongoose": "^8.3.0", "multer": "^1.4.5-lts.1", + "nest-winston": "^1.9.7", "reflect-metadata": "^0.2.0", - "rxjs": "^7.8.1" + "rxjs": "^7.8.1", + "winston": "^3.16.0" }, "devDependencies": { "@nestjs/cli": "^10.0.0", diff --git a/src/api/decisions/decisions.service.spec.ts b/src/api/decisions/decisions.service.spec.ts index 6b76022..8b57263 100644 --- a/src/api/decisions/decisions.service.spec.ts +++ b/src/api/decisions/decisions.service.spec.ts @@ -1,5 +1,6 @@ import { ConfigService } from '@nestjs/config'; import { Test, TestingModule } from '@nestjs/testing'; +import { Logger } from '@nestjs/common'; import { ZenEngine, ZenDecision, ZenEvaluateOptions } from '@gorules/zen-engine'; import { DecisionsService } from './decisions.service'; import { ValidationService } from './validations/validations.service'; @@ -25,7 +26,13 @@ describe('DecisionsService', () => { }; const module: TestingModule = await Test.createTestingModule({ - providers: [ConfigService, DecisionsService, ValidationService, { provide: ZenEngine, useValue: mockEngine }], + providers: [ + ConfigService, + DecisionsService, + ValidationService, + { provide: ZenEngine, useValue: mockEngine }, + Logger, + ], }).compile(); service = module.get(DecisionsService); diff --git a/src/api/decisions/decisions.service.ts b/src/api/decisions/decisions.service.ts index 4f64eda..6707a9e 100644 --- a/src/api/decisions/decisions.service.ts +++ b/src/api/decisions/decisions.service.ts @@ -1,4 +1,4 @@ -import { Injectable, HttpException, HttpStatus } from '@nestjs/common'; +import { Injectable, HttpException, HttpStatus, Logger } from '@nestjs/common'; import { ZenEngine, ZenEvaluateOptions } from '@gorules/zen-engine'; import { ConfigService } from '@nestjs/config'; import { RuleContent } from '../ruleMapping/ruleMapping.interface'; @@ -11,7 +11,10 @@ export class DecisionsService { engine: ZenEngine; rulesDirectory: string; - constructor(private configService: ConfigService) { + constructor( + private configService: ConfigService, + private readonly logger: Logger, + ) { this.rulesDirectory = this.configService.get('RULES_DIRECTORY'); const loader = async (key: string) => readFileSafely(this.rulesDirectory, key); this.engine = new ZenEngine({ loader }); @@ -28,7 +31,7 @@ export class DecisionsService { if (error instanceof ValidationError) { throw new ValidationError(`Invalid input: ${error.message}`); } else { - console.error(error.message); + this.logger.warn(error.message); throw new Error(`Failed to run decision: ${error.message}`); } } diff --git a/src/api/klamm/klamm.module.ts b/src/api/klamm/klamm.module.ts index 59fb290..33f2a0f 100644 --- a/src/api/klamm/klamm.module.ts +++ b/src/api/klamm/klamm.module.ts @@ -1,4 +1,4 @@ -import { Module } from '@nestjs/common'; +import { Module, Logger } from '@nestjs/common'; import { MongooseModule } from '@nestjs/mongoose'; import { RuleDataModule } from '../ruleData/ruleData.module'; import { RuleMappingModule } from '../ruleMapping/ruleMapping.module'; @@ -14,6 +14,6 @@ import { KlammService } from './klamm.service'; MongooseModule.forFeature([{ name: KlammSyncMetadata.name, schema: KlammSyncMetadataSchema }]), ], controllers: [KlammController], - providers: [KlammService, DocumentsService], + providers: [KlammService, DocumentsService, Logger], }) export class KlammModule {} diff --git a/src/api/klamm/klamm.service.spec.ts b/src/api/klamm/klamm.service.spec.ts index 526754a..12e7434 100644 --- a/src/api/klamm/klamm.service.spec.ts +++ b/src/api/klamm/klamm.service.spec.ts @@ -1,4 +1,5 @@ import { Model } from 'mongoose'; +import { Logger } from '@nestjs/common'; import { KlammService, GITHUB_RULES_REPO } from './klamm.service'; import { RuleDataService } from '../ruleData/ruleData.service'; import { RuleMappingService } from '../ruleMapping/ruleMapping.service'; @@ -29,7 +30,7 @@ describe('KlammService', () => { findOne: jest.fn(), } as unknown as Model; - service = new KlammService(ruleDataService, ruleMappingService, documentsService, klammSyncMetadata); + service = new KlammService(ruleDataService, ruleMappingService, documentsService, klammSyncMetadata, new Logger()); }); afterEach(() => { diff --git a/src/api/klamm/klamm.service.ts b/src/api/klamm/klamm.service.ts index 51a4264..491da78 100644 --- a/src/api/klamm/klamm.service.ts +++ b/src/api/klamm/klamm.service.ts @@ -1,4 +1,4 @@ -import { Injectable, HttpException, HttpStatus } from '@nestjs/common'; +import { Injectable, HttpException, HttpStatus, Logger } from '@nestjs/common'; import { Model } from 'mongoose'; import { InjectModel } from '@nestjs/mongoose'; import axios, { AxiosInstance } from 'axios'; @@ -29,6 +29,7 @@ export class KlammService { private readonly ruleMappingService: RuleMappingService, private readonly documentsService: DocumentsService, @InjectModel(KlammSyncMetadata.name) private klammSyncMetadata: Model, + private readonly logger: Logger, ) { this.axiosKlammInstance = axios.create({ headers: { Authorization: `Bearer ${process.env.KLAMM_API_AUTH_TOKEN}`, 'Content-Type': 'application/json' }, @@ -42,21 +43,21 @@ export class KlammService { async onModuleInit() { try { - console.info('Syncing existing rules with Klamm...'); + this.logger.log('Syncing existing rules with Klamm...'); const { updatedFilesSinceLastDeploy, lastCommitAsyncTimestamp } = await this._getUpdatedFilesFromGithub(); if (lastCommitAsyncTimestamp != undefined) { - console.info( + this.logger.log( `Files updated since last deploy up to ${new Date(lastCommitAsyncTimestamp)}:`, updatedFilesSinceLastDeploy, ); await this._syncRules(updatedFilesSinceLastDeploy); - console.info('Completed syncing existing rules with Klamm'); + this.logger.log('Completed syncing existing rules with Klamm'); await this._updateLastSyncTimestamp(lastCommitAsyncTimestamp); } else { - console.info('Klamm file syncing up to date'); + this.logger.log('Klamm file syncing up to date'); } } catch (error) { - console.error('Unable to sync latest updates to Klamm:', error.message); + this.logger.error('Unable to sync latest updates to Klamm:', error.message); } } @@ -98,12 +99,12 @@ export class KlammService { const rule = await this.ruleDataService.getRuleDataByFilepath(ruleFilepath); if (rule) { await this._syncRuleWithKlamm(rule); - console.info(`Rule ${rule.name} synced`); + this.logger.log(`Rule ${rule.name} synced`); } else { - console.warn(`No rule found for changed file: ${ruleFilepath}`); + this.logger.warn(`No rule found for changed file: ${ruleFilepath}`); } } catch (error) { - console.error(`Failed to sync rule from file ${ruleFilepath}:`, error.message); + this.logger.error(`Failed to sync rule from file ${ruleFilepath}:`, error.message); errors.push(`Failed to sync rule from file ${ruleFilepath}: ${error.message}`); } } @@ -121,7 +122,7 @@ export class KlammService { const timestamp = await this._getLastSyncTimestamp(); const date = new Date(timestamp); const formattedDate = date.toISOString().split('.')[0] + 'Z'; // Format required for github api - console.log(`Getting files from Github from ${formattedDate} onwards...`); + this.logger.log(`Getting files from Github from ${formattedDate} onwards...`); // Fetch commits since the specified timestamp const commitsResponse = await this.axiosGithubInstance.get( `${GITHUB_RULES_REPO}/commits?since=${formattedDate}&sha=${process.env.GITHUB_RULES_BRANCH}`, @@ -144,7 +145,7 @@ export class KlammService { } return { updatedFilesSinceLastDeploy: Array.from(updatedFiles), lastCommitAsyncTimestamp }; } catch (error) { - console.error('Error fetching updated files from GitHub:', error); + this.logger.error('Error fetching updated files from GitHub:', error); throw new Error('Error fetching updated files from GitHub'); } } @@ -166,7 +167,7 @@ export class KlammService { // Add or update the rule in Klamm await this._addOrUpdateRuleInKlamm(payloadToAddOrUpdate); } catch (error) { - console.error(`Error syncing ${rule.name}`, error.message); + this.logger.error(`Error syncing ${rule.name}`, error.message); throw new Error(`Error syncing ${rule.name}`); } } @@ -181,7 +182,7 @@ export class KlammService { const outputResults = this._getFieldsFromIds(klammFields, outputIds); return { inputs: inputResults, outputs: outputResults }; } catch (error) { - console.error(`Error getting input/output fields for rule ${rule.name}`, error.message); + this.logger.error(`Error getting input/output fields for rule ${rule.name}`, error.message); throw new Error(`Error getting input/output fields for rule ${rule.name}`); } } @@ -201,7 +202,7 @@ export class KlammService { const response = await this.axiosKlammInstance.get(`${process.env.KLAMM_API_URL}/api/brerules`); return response.data.data; } catch (error) { - console.error('Error fetching fields from Klamm', error.message); + this.logger.error('Error fetching fields from Klamm', error.message); throw new Error(`Error fetching fields from Klamm: ${error.message}`); } } @@ -217,7 +218,7 @@ export class KlammService { const results = await Promise.all(promises); return results.map((response) => response); } catch (error) { - console.error(`Error gettting child rules for ${rule.name}:`, error.message); + this.logger.error(`Error gettting child rules for ${rule.name}:`, error.message); throw new Error(`Error gettting child rules for ${rule.name}`); } } @@ -239,7 +240,7 @@ export class KlammService { }); return data.data[0]; } catch (error) { - console.error(`Error getting rule ${ruleName} from Klamm:`, error.message); + this.logger.error(`Error getting rule ${ruleName} from Klamm:`, error.message); throw new Error(`Error getting rule ${ruleName} from Klamm`); } } @@ -248,7 +249,7 @@ export class KlammService { try { await this.axiosKlammInstance.post(`${process.env.KLAMM_API_URL}/api/brerules`, rulePayload); } catch (error) { - console.error('Error adding rule to Klamm:', error.message); + this.logger.error('Error adding rule to Klamm:', error.message); throw new Error('Error adding rule to Klamm'); } } @@ -257,7 +258,7 @@ export class KlammService { try { await this.axiosKlammInstance.put(`${process.env.KLAMM_API_URL}/api/brerules/${currentKlamRuleId}`, rulePayload); } catch (error) { - console.error(`Error updating rule ${currentKlamRuleId} in Klamm:`, error.message); + this.logger.error(`Error updating rule ${currentKlamRuleId} in Klamm:`, error.message); throw new Error(`Error updating rule ${currentKlamRuleId} in Klamm`); } } @@ -270,7 +271,7 @@ export class KlammService { { upsert: true, new: true }, ); } catch (error) { - console.error('Failed to update last sync timestamp', error.message); + this.logger.error('Failed to update last sync timestamp', error.message); throw new Error('Failed to update last sync timestamp'); } } @@ -280,7 +281,7 @@ export class KlammService { const record = await this.klammSyncMetadata.findOne({ key: 'singleton' }); return record ? record.lastSyncTimestamp : 0; } catch (error) { - console.error('Failed to get last sync timestamp:', error.message); + this.logger.error('Failed to get last sync timestamp:', error.message); throw new Error('Failed to get last sync timestamp'); } } diff --git a/src/api/ruleData/ruleData.module.ts b/src/api/ruleData/ruleData.module.ts index 531357f..a7da94c 100644 --- a/src/api/ruleData/ruleData.module.ts +++ b/src/api/ruleData/ruleData.module.ts @@ -1,4 +1,4 @@ -import { Module } from '@nestjs/common'; +import { Logger, Module } from '@nestjs/common'; import { MongooseModule } from '@nestjs/mongoose'; import { RuleData, RuleDataSchema } from './ruleData.schema'; import { RuleDraft, RuleDraftSchema } from './ruleDraft.schema'; @@ -14,7 +14,7 @@ import { DocumentsService } from '../documents/documents.service'; ]), ], controllers: [RuleDataController], - providers: [RuleDataService, DocumentsService], + providers: [RuleDataService, DocumentsService, Logger], exports: [RuleDataService], }) export class RuleDataModule {} diff --git a/src/api/ruleData/ruleData.service.spec.ts b/src/api/ruleData/ruleData.service.spec.ts index b58f84d..d027277 100644 --- a/src/api/ruleData/ruleData.service.spec.ts +++ b/src/api/ruleData/ruleData.service.spec.ts @@ -1,4 +1,5 @@ import { Test, TestingModule } from '@nestjs/testing'; +import { Logger } from '@nestjs/common'; import { getModelToken } from '@nestjs/mongoose'; import { DocumentsService } from '../documents/documents.service'; import { RuleDataService } from './ruleData.service'; @@ -45,6 +46,7 @@ export const mockServiceProviders = [ getAllJSONFiles: jest.fn().mockResolvedValue(['doc1.json', 'doc2.json']), }, }, + Logger, ]; describe('RuleDataService', () => { diff --git a/src/api/ruleData/ruleData.service.ts b/src/api/ruleData/ruleData.service.ts index b13a897..16b49f1 100644 --- a/src/api/ruleData/ruleData.service.ts +++ b/src/api/ruleData/ruleData.service.ts @@ -1,6 +1,6 @@ import { ObjectId } from 'mongodb'; import { Model, Types } from 'mongoose'; -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import { InjectModel } from '@nestjs/mongoose'; import axios from 'axios'; import { DocumentsService } from '../documents/documents.service'; @@ -18,10 +18,11 @@ export class RuleDataService { @InjectModel(RuleData.name) private ruleDataModel: Model, @InjectModel(RuleDraft.name) private ruleDraftModel: Model, private documentsService: DocumentsService, + private readonly logger: Logger, ) {} async onModuleInit() { - console.info('Syncing existing rules with any updates to the rules repository'); + this.logger.log('Syncing existing rules with any updates to the rules repository'); const existingRules = await this.getAllRuleData(); const { data: existingRuleData } = existingRules; this.updateCategories(existingRuleData); @@ -161,7 +162,7 @@ export class RuleDataService { this.updateCategories(existingRules.data); return response; } catch (error) { - console.error(error.message); + this.logger.error(error.message); throw new Error(`Failed to add rule data: ${error.message}`); } } @@ -179,7 +180,7 @@ export class RuleDataService { Object.assign(existingRuleData, updatedData); return await existingRuleData.save(); } catch (error) { - console.error('Error updating rule', error.message); + this.logger.error('Error updating rule', error.message); throw new Error(`Failed to update rule data: ${error.message}`); } } @@ -220,7 +221,7 @@ export class RuleDataService { }); } } catch (error) { - console.error('Error updating review status:', error.message); + this.logger.error('Error updating review status:', error.message); } } diff --git a/src/api/scenarioData/scenarioData.service.spec.ts b/src/api/scenarioData/scenarioData.service.spec.ts index 200a5dd..c5bff77 100644 --- a/src/api/scenarioData/scenarioData.service.spec.ts +++ b/src/api/scenarioData/scenarioData.service.spec.ts @@ -1,4 +1,5 @@ import { Test, TestingModule } from '@nestjs/testing'; +import { Logger } from '@nestjs/common'; import { ScenarioDataService } from './scenarioData.service'; import { getModelToken } from '@nestjs/mongoose'; import { Types, Model } from 'mongoose'; @@ -69,6 +70,7 @@ describe('ScenarioDataService', () => { get: jest.fn().mockReturnValue('mocked_value'), }, }, + Logger, ], }).compile(); diff --git a/src/api/scenarioData/scenarioData.service.ts b/src/api/scenarioData/scenarioData.service.ts index 80e69ac..ef837f4 100644 --- a/src/api/scenarioData/scenarioData.service.ts +++ b/src/api/scenarioData/scenarioData.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import { InjectModel } from '@nestjs/mongoose'; import { Model, Types } from 'mongoose'; import { ScenarioData, ScenarioDataDocument } from './scenarioData.schema'; @@ -26,6 +26,7 @@ export class ScenarioDataService { private ruleMappingService: RuleMappingService, private documentsService: DocumentsService, @InjectModel(ScenarioData.name) private scenarioDataModel: Model, + private readonly logger: Logger, ) {} async getAllScenarioData(): Promise { @@ -55,7 +56,7 @@ export class ScenarioDataService { const response = await newScenarioData.save(); return response; } catch (error) { - console.error('Error in createScenarioData:', error); + this.logger.error('Error in createScenarioData:', error); throw new Error(`Failed to add scenario data: ${error.message}`); } } @@ -147,7 +148,7 @@ export class ScenarioDataService { results[scenario.title.toString()] = scenarioResult; } catch (error) { - console.error(`Error running decision for scenario ${scenario._id}: ${error.message}`); + this.logger.error(`Error running decision for scenario ${scenario._id}: ${error.message}`); const scenarioResult = { inputs: formattedVariablesObject, outputs: null, @@ -511,7 +512,7 @@ export class ScenarioDataService { }, }; } catch (error) { - console.error(`Error running decision for scenario ${title}: ${error.message}`); + this.logger.error(`Error running decision for scenario ${title}: ${error.message}`); return { title, scenarioResult: { diff --git a/src/app.module.ts b/src/app.module.ts index d341f79..a175527 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,4 +1,4 @@ -import { Module } from '@nestjs/common'; +import { Logger, Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; import { MongooseModule } from '@nestjs/mongoose'; import { GithubAuthModule } from './auth/github-auth/github-auth.module'; @@ -31,6 +31,6 @@ import { ScenarioDataService } from './api/scenarioData/scenarioData.service'; KlammModule, ], controllers: [DecisionsController, DocumentsController, ScenarioDataController], - providers: [DecisionsService, DocumentsService, ScenarioDataService], + providers: [Logger, DecisionsService, DocumentsService, ScenarioDataService], }) export class AppModule {} diff --git a/src/auth/github-auth/github-auth.controller.spec.ts b/src/auth/github-auth/github-auth.controller.spec.ts index dfbd0cf..2ed28ea 100644 --- a/src/auth/github-auth/github-auth.controller.spec.ts +++ b/src/auth/github-auth/github-auth.controller.spec.ts @@ -1,4 +1,5 @@ import { Test, TestingModule } from '@nestjs/testing'; +import { Logger } from '@nestjs/common'; import { GithubAuthController } from './github-auth.controller'; import { GithubAuthService } from './github-auth.service'; import { Response } from 'express'; @@ -19,6 +20,7 @@ describe('GithubAuthController', () => { getGithubUser: jest.fn(), }, }, + Logger, ], }).compile(); diff --git a/src/auth/github-auth/github-auth.controller.ts b/src/auth/github-auth/github-auth.controller.ts index 4b4574b..b8c8f74 100644 --- a/src/auth/github-auth/github-auth.controller.ts +++ b/src/auth/github-auth/github-auth.controller.ts @@ -1,9 +1,12 @@ -import { Controller, Get, Query, Redirect, Res, Post } from '@nestjs/common'; +import { Controller, Get, Query, Redirect, Res, Post, Logger } from '@nestjs/common'; import { GithubAuthService } from './github-auth.service'; @Controller('auth/github') export class GithubAuthController { - constructor(private readonly authService: GithubAuthService) {} + constructor( + private readonly authService: GithubAuthService, + private readonly logger: Logger, + ) {} /** * Redirect to github for oauth flow diff --git a/src/auth/github-auth/github-auth.module.ts b/src/auth/github-auth/github-auth.module.ts index eab8c8b..09ff360 100644 --- a/src/auth/github-auth/github-auth.module.ts +++ b/src/auth/github-auth/github-auth.module.ts @@ -1,9 +1,9 @@ -import { Module } from '@nestjs/common'; +import { Logger, Module } from '@nestjs/common'; import { GithubAuthService } from './github-auth.service'; import { GithubAuthController } from './github-auth.controller'; @Module({ controllers: [GithubAuthController], - providers: [GithubAuthService], + providers: [GithubAuthService, Logger], }) export class GithubAuthModule {} diff --git a/src/auth/github-auth/github-auth.service.spec.ts b/src/auth/github-auth/github-auth.service.spec.ts index 9403bdb..df02b0f 100644 --- a/src/auth/github-auth/github-auth.service.spec.ts +++ b/src/auth/github-auth/github-auth.service.spec.ts @@ -1,4 +1,5 @@ import { Test, TestingModule } from '@nestjs/testing'; +import { Logger } from '@nestjs/common'; import { GithubAuthService } from './github-auth.service'; import axios from 'axios'; @@ -10,7 +11,7 @@ describe('GithubAuthService', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ - providers: [GithubAuthService], + providers: [GithubAuthService, Logger], }).compile(); service = module.get(GithubAuthService); diff --git a/src/auth/github-auth/github-auth.service.ts b/src/auth/github-auth/github-auth.service.ts index 7ddfd98..2ca32c3 100644 --- a/src/auth/github-auth/github-auth.service.ts +++ b/src/auth/github-auth/github-auth.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import axios from 'axios'; const GITHUB_OAUTH_URL = 'https://github.com/login/oauth'; @@ -8,6 +8,8 @@ const GITHUB_USER_URL = 'https://api.github.com/user'; export class GithubAuthService { private readonly redirectUri = `${process.env.FRONTEND_URI}/auth/github/callback`; + constructor(private readonly logger: Logger) {} + /** * Gnerates URL for GitHub oauth flow * @param returnUrl the URL on our site we want to return to after going through github oauth flow @@ -59,7 +61,7 @@ export class GithubAuthService { }); return response.data; } catch (error) { - console.error('Error fetching GitHub user:', error); + this.logger.error('Error fetching GitHub user:', error); throw new Error('Failed to fetch GitHub user information'); } } diff --git a/src/main.spec.ts b/src/main.spec.ts index bf64461..05efe24 100644 --- a/src/main.spec.ts +++ b/src/main.spec.ts @@ -17,6 +17,6 @@ jest.mock('@nestjs/core', () => { describe('main.ts', () => { it('should bootstrap the application', async () => { await require('./main'); - expect(NestFactory.create).toHaveBeenCalledWith(AppModule); + expect(NestFactory.create).toHaveBeenCalledWith(AppModule, expect.any(Object)); }); }); diff --git a/src/main.ts b/src/main.ts index 175d446..79ceea5 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,14 +1,25 @@ import { NestFactory } from '@nestjs/core'; import { NestExpressApplication } from '@nestjs/platform-express'; +import * as winston from 'winston'; +import { WinstonModule } from 'nest-winston'; import { AppModule } from './app.module'; +import { winstonConfig } from './winston-config.service'; async function bootstrap() { - const app = await NestFactory.create(AppModule); + // Setup app with logging + const logger = winston.createLogger(winstonConfig); + const app = await NestFactory.create(AppModule, { + logger: WinstonModule.createLogger({ + instance: logger, // Pass the custom Winston instance + }), + }); + // Enable CORS for frontend app.enableCors({ origin: process.env.FRONTEND_URI, }); + // Start the app on the specified port const port = process.env.PORT || 3000; await app.listen(process.env.PORT || 3000); - console.log(`Server is running on port ${port} with ${process.env.FRONTEND_URI} allowed origins.`); + logger.info(`Server is running on port ${port} with ${process.env.FRONTEND_URI} allowed origins.`); } bootstrap(); diff --git a/src/utils/readFile.ts b/src/utils/readFile.ts index 0cc8f59..ad4622a 100644 --- a/src/utils/readFile.ts +++ b/src/utils/readFile.ts @@ -22,7 +22,6 @@ export const readFileSafely = async (rulesDirectory: string, ruleFileName: strin const filePath = path.resolve(rulesDirectory, ruleFileName); // Check if the resolved path is within the intended directory if (!filePath.startsWith(path.resolve(rulesDirectory))) { - console.error('Path traversal detected'); throw new FileNotFoundError('Path traversal detected'); } // Check if the file is found diff --git a/src/winston-config.service.ts b/src/winston-config.service.ts new file mode 100644 index 0000000..f83c42a --- /dev/null +++ b/src/winston-config.service.ts @@ -0,0 +1,16 @@ +import * as winston from 'winston'; + +const isDevelopment = process.env.NODE_ENV !== 'production'; + +export const winstonConfig = { + format: isDevelopment + ? winston.format.combine( + winston.format.timestamp(), + winston.format.colorize(), + winston.format.printf(({ timestamp, level, message }) => { + return `${timestamp} [${level}]: ${message}`; + }), // Custom formatting for development + ) + : winston.format.json(), // Format to Kibana-compatible JSON + transports: [new winston.transports.Console()], +};