From b29a52703c3d988453bf9648d115ab02b65fd861 Mon Sep 17 00:00:00 2001 From: code-storm Date: Thu, 13 Mar 2025 17:34:25 +0530 Subject: [PATCH 1/2] Env variable and winston support --- .gitignore | 3 +- dist/app.js | 7 +- dist/app.js.map | 2 +- dist/logger.js | 31 ++++++ dist/logger.js.map | 1 + package-lock.json | 256 ++++++++++++++++++++++++++++++++++++++++++++- package.json | 6 +- src/app.ts | 7 +- src/logger.ts | 29 +++++ tsconfig.json | 16 ++- 10 files changed, 345 insertions(+), 13 deletions(-) create mode 100644 dist/logger.js create mode 100644 dist/logger.js.map create mode 100644 src/logger.ts diff --git a/.gitignore b/.gitignore index a75d301..13c1932 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,5 @@ npm-debug.log* yarn-debug.log* -yarn-error.log* \ No newline at end of file +yarn-error.log* +*.log \ No newline at end of file diff --git a/dist/app.js b/dist/app.js index 49cc5c7..85534de 100644 --- a/dist/app.js +++ b/dist/app.js @@ -4,15 +4,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) { }; Object.defineProperty(exports, "__esModule", { value: true }); const express_1 = __importDefault(require("express")); +const logger_1 = require("./logger"); const app = (0, express_1.default)(); -const port = 3000; +const port = process.env.PORT || 3000; app.get('/', (req, res) => { - res.send('GET request is working'); + res.send('GET request is working here'); }); app.listen(port, err => { if (err) { return console.error(err); } - return console.log(`server is listening on ${port}`); + return logger_1.logger.info(`${process.env.NODE_ENV || ''} server is listening on http://localhost:${port}`); }); //# sourceMappingURL=app.js.map \ No newline at end of file diff --git a/dist/app.js.map b/dist/app.js.map index 12c1aa0..54cd7ec 100644 --- a/dist/app.js.map +++ b/dist/app.js.map @@ -1 +1 @@ -{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":";;;;;AAAA,sDAA8B;AAE9B,MAAM,GAAG,GAAG,IAAA,iBAAO,GAAE,CAAC;AACtB,MAAM,IAAI,GAAG,IAAI,CAAC;AAClB,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IACtB,GAAG,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAA;AACtC,CAAC,CAAC,CAAC;AAEH,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE;IACnB,IAAI,GAAG,EAAE,CAAC;QACN,OAAO,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,OAAO,CAAC,GAAG,CAAC,0BAA0B,IAAI,EAAE,CAAC,CAAA;AACxD,CAAC,CAAC,CAAC"} \ No newline at end of file +{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":";;;;;AAAA,sDAA8B;AAC9B,qCAAkC;AAElC,MAAM,GAAG,GAAG,IAAA,iBAAO,GAAE,CAAC;AACtB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC;AACtC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IACtB,GAAG,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAA;AAC3C,CAAC,CAAC,CAAC;AAEH,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE;IACnB,IAAI,GAAG,EAAE,CAAC;QACN,OAAO,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,eAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,4CAA4C,IAAI,EAAE,CAAC,CAAA;AACvG,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/logger.js b/dist/logger.js new file mode 100644 index 0000000..3ed10eb --- /dev/null +++ b/dist/logger.js @@ -0,0 +1,31 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.logger = void 0; +const winston_1 = require("winston"); +exports.logger = (0, winston_1.createLogger)({ + level: 'info', + format: winston_1.format.json(), + defaultMeta: { service: 'node-typescript-express' }, + transports: [ + // + // - Write all logs with importance level of `error` or higher to `error.log` + // (i.e., error, fatal, but not other levels) + // + new winston_1.transports.File({ filename: 'error.log', level: 'error' }), + // + // - Write all logs with importance level of `info` or higher to `combined.log` + // (i.e., fatal, error, warn, and info, but not trace) + // + new winston_1.transports.File({ filename: 'combined.log' }), + ], +}); +// +// If we're not in production then log to the `console` with the format: +// `${info.level}: ${info.message} JSON.stringify({ ...rest }) ` +// +if (process.env.NODE_ENV !== 'production') { + exports.logger.add(new winston_1.transports.Console({ + format: winston_1.format.simple(), + })); +} +//# sourceMappingURL=logger.js.map \ No newline at end of file diff --git a/dist/logger.js.map b/dist/logger.js.map new file mode 100644 index 0000000..b2fb8f3 --- /dev/null +++ b/dist/logger.js.map @@ -0,0 +1 @@ +{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":";;;AAAA,qCAA0D;AAE7C,QAAA,MAAM,GAAG,IAAA,sBAAY,EAAC;IACjC,KAAK,EAAE,MAAM;IACb,MAAM,EAAE,gBAAM,CAAC,IAAI,EAAE;IACrB,WAAW,EAAE,EAAE,OAAO,EAAE,yBAAyB,EAAE;IACnD,UAAU,EAAE;QACV,EAAE;QACF,6EAA6E;QAC7E,+CAA+C;QAC/C,EAAE;QACF,IAAI,oBAAU,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;QAC9D,EAAE;QACF,+EAA+E;QAC/E,wDAAwD;QACxD,EAAE;QACF,IAAI,oBAAU,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC;KAClD;CACF,CAAC,CAAC;AAEH,EAAE;AACF,wEAAwE;AACxE,gEAAgE;AAChE,EAAE;AACF,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;IAC1C,cAAM,CAAC,GAAG,CAAC,IAAI,oBAAU,CAAC,OAAO,CAAC;QAChC,MAAM,EAAE,gBAAM,CAAC,MAAM,EAAE;KACxB,CAAC,CAAC,CAAC;AACN,CAAC"} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index aaf042e..ba94052 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,8 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "express": "^5.0.1" + "express": "^5.0.1", + "winston": "^3.17.0" }, "devDependencies": { "@eslint/js": "^9.22.0", @@ -20,6 +21,26 @@ "typescript-eslint": "^8.26.1" } }, + "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==", + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.5.0.tgz", @@ -397,6 +418,12 @@ "@types/send": "*" } }, + "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==", + "license": "MIT" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.26.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.26.1.tgz", @@ -679,6 +706,12 @@ "dev": true, "license": "Python-2.0" }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -810,6 +843,16 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "license": "MIT", + "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", @@ -827,9 +870,43 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, "license": "MIT" }, + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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==", + "license": "MIT" + }, + "node_modules/colorspace": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", + "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", + "license": "MIT", + "dependencies": { + "color": "^3.1.3", + "text-hex": "1.0.x" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -954,6 +1031,12 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "license": "MIT" }, + "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==", + "license": "MIT" + }, "node_modules/encodeurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", @@ -1303,6 +1386,12 @@ "reusify": "^1.0.4" } }, + "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==", + "license": "MIT" + }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -1384,6 +1473,12 @@ "dev": true, "license": "ISC" }, + "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==", + "license": "MIT" + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -1607,6 +1702,12 @@ "node": ">= 0.10" } }, + "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==", + "license": "MIT" + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -1646,6 +1747,18 @@ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", "license": "MIT" }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -1697,6 +1810,12 @@ "json-buffer": "3.0.1" } }, + "node_modules/kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", + "license": "MIT" + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -1734,6 +1853,23 @@ "dev": true, "license": "MIT" }, + "node_modules/logform": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz", + "integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==", + "license": "MIT", + "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/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -1886,6 +2022,15 @@ "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==", + "license": "MIT", + "dependencies": { + "fn.name": "1.x.x" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -2105,6 +2250,20 @@ "node": ">=0.10.0" } }, + "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==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -2184,6 +2343,15 @@ ], "license": "MIT" }, + "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==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -2372,6 +2540,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "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==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -2381,6 +2567,15 @@ "node": ">= 0.8" } }, + "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==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -2407,6 +2602,12 @@ "node": ">=8" } }, + "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==", + "license": "MIT" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -2429,6 +2630,15 @@ "node": ">=0.6" } }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, "node_modules/ts-api-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz", @@ -2532,6 +2742,12 @@ "punycode": "^2.1.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -2566,6 +2782,42 @@ "node": ">= 8" } }, + "node_modules/winston": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.17.0.tgz", + "integrity": "sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw==", + "license": "MIT", + "dependencies": { + "@colors/colors": "^1.6.0", + "@dabh/diagnostics": "^2.0.2", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.7.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.9.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-transport": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz", + "integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==", + "license": "MIT", + "dependencies": { + "logform": "^2.7.0", + "readable-stream": "^3.6.2", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", diff --git a/package.json b/package.json index 16b473d..e9a27b9 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "", "main": "index.js", "scripts": { - "start": "tsc && node dist/app.js", + "start": "tsc && NODE_ENV=development node dist/app.js", + "dev": "tsc -w & NODE_ENV=development node --env-file=.env.local --watch dist/app.js", "test": "echo \"Error: no test specified\"" }, "author": "Mudit Khandelwal (code-storm)", @@ -18,6 +19,7 @@ "typescript-eslint": "^8.26.1" }, "dependencies": { - "express": "^5.0.1" + "express": "^5.0.1", + "winston": "^3.17.0" } } diff --git a/src/app.ts b/src/app.ts index 4421be0..c18f4ad 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,14 +1,15 @@ import express from "express"; +import { logger } from "./logger"; const app = express(); -const port = 3000; +const port = process.env.PORT || 3000; app.get('/', (req, res) => { - res.send('GET request is working') + res.send('GET request is working here') }); app.listen(port, err => { if (err) { return console.error(err); } - return console.log(`server is listening on ${port}`) + return logger.info(`${process.env.NODE_ENV || ''} server is listening on http://localhost:${port}`) }); \ No newline at end of file diff --git a/src/logger.ts b/src/logger.ts new file mode 100644 index 0000000..a7eb8a1 --- /dev/null +++ b/src/logger.ts @@ -0,0 +1,29 @@ +import { createLogger, format, transports } from "winston" + +export const logger = createLogger({ + level: 'info', + format: format.json(), + defaultMeta: { service: 'node-typescript-express' }, + transports: [ + // + // - Write all logs with importance level of `error` or higher to `error.log` + // (i.e., error, fatal, but not other levels) + // + new transports.File({ filename: 'error.log', level: 'error' }), + // + // - Write all logs with importance level of `info` or higher to `combined.log` + // (i.e., fatal, error, warn, and info, but not trace) + // + new transports.File({ filename: 'combined.log' }), + ], +}); + +// +// If we're not in production then log to the `console` with the format: +// `${info.level}: ${info.message} JSON.stringify({ ...rest }) ` +// +if (process.env.NODE_ENV !== 'production') { + logger.add(new transports.Console({ + format: format.simple(), + })); +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index bd2ebf9..a55622e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,7 +5,21 @@ "target": "es6", "moduleResolution": "node", "sourceMap": true, - "outDir": "dist" + "outDir": "dist", + "rootDir": "src" + }, + "watchOptions": { + "watchFile": "useFsEvents", + "watchDirectory": "useFsEvents", + // Poll files for updates more frequently + // when they're updated a lot. + "fallbackPolling": "dynamicPriority", + // Don't coalesce watch notification + "synchronousWatchDirectory": true, + // Finally, two additional settings for reducing the amount of possible + // files to track work from these directories + "excludeDirectories": ["**/node_modules", "dist"], + "excludeFiles": ["build/fileWhichChangesOften.ts"] }, "lib": ["es2015"] } \ No newline at end of file From 438e142b69795e0d20c245365b037725abbcf525 Mon Sep 17 00:00:00 2001 From: code-storm Date: Fri, 14 Mar 2025 16:32:36 +0530 Subject: [PATCH 2/2] Added monogodb and mongoose support --- dist/app.js | 6 + dist/app.js.map | 2 +- dist/config/db.js | 24 +++ dist/config/db.js.map | 1 + dist/controllers/userController.js | 77 ++++++++++ dist/controllers/userController.js.map | 1 + dist/models/index.js | 6 + dist/models/index.js.map | 1 + dist/models/userModel.js | 75 ++++++++++ dist/models/userModel.js.map | 1 + dist/routes/userRoutes.js | 12 ++ dist/routes/userRoutes.js.map | 1 + dist/services/userService.js | 38 +++++ dist/services/userService.js.map | 1 + package-lock.json | 198 ++++++++++++++++++++++++- package.json | 4 +- samplecurl.txt | 8 + src/app.ts | 12 +- src/config/db.ts | 14 ++ src/controllers/userController.ts | 54 +++++++ src/models/index.ts | 1 + src/models/userModel.ts | 52 +++++++ src/routes/userRoutes.ts | 12 ++ src/services/userService.ts | 20 +++ 24 files changed, 617 insertions(+), 4 deletions(-) create mode 100644 dist/config/db.js create mode 100644 dist/config/db.js.map create mode 100644 dist/controllers/userController.js create mode 100644 dist/controllers/userController.js.map create mode 100644 dist/models/index.js create mode 100644 dist/models/index.js.map create mode 100644 dist/models/userModel.js create mode 100644 dist/models/userModel.js.map create mode 100644 dist/routes/userRoutes.js create mode 100644 dist/routes/userRoutes.js.map create mode 100644 dist/services/userService.js create mode 100644 dist/services/userService.js.map create mode 100644 samplecurl.txt create mode 100644 src/config/db.ts create mode 100644 src/controllers/userController.ts create mode 100644 src/models/index.ts create mode 100644 src/models/userModel.ts create mode 100644 src/routes/userRoutes.ts create mode 100644 src/services/userService.ts diff --git a/dist/app.js b/dist/app.js index 85534de..6af7645 100644 --- a/dist/app.js +++ b/dist/app.js @@ -5,8 +5,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) { Object.defineProperty(exports, "__esModule", { value: true }); const express_1 = __importDefault(require("express")); const logger_1 = require("./logger"); +const userRoutes_1 = __importDefault(require("./routes/userRoutes")); +const db_1 = __importDefault(require("./config/db")); const app = (0, express_1.default)(); const port = process.env.PORT || 3000; +(0, db_1.default)(); +app.use(express_1.default.json()); +app.use('/api', userRoutes_1.default); app.get('/', (req, res) => { res.send('GET request is working here'); }); @@ -16,4 +21,5 @@ app.listen(port, err => { } return logger_1.logger.info(`${process.env.NODE_ENV || ''} server is listening on http://localhost:${port}`); }); +exports.default = app; //# sourceMappingURL=app.js.map \ No newline at end of file diff --git a/dist/app.js.map b/dist/app.js.map index 54cd7ec..0635b39 100644 --- a/dist/app.js.map +++ b/dist/app.js.map @@ -1 +1 @@ -{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":";;;;;AAAA,sDAA8B;AAC9B,qCAAkC;AAElC,MAAM,GAAG,GAAG,IAAA,iBAAO,GAAE,CAAC;AACtB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC;AACtC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IACtB,GAAG,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAA;AAC3C,CAAC,CAAC,CAAC;AAEH,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE;IACnB,IAAI,GAAG,EAAE,CAAC;QACN,OAAO,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,eAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,4CAA4C,IAAI,EAAE,CAAC,CAAA;AACvG,CAAC,CAAC,CAAC"} \ No newline at end of file +{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":";;;;;AAAA,sDAA8B;AAC9B,qCAAkC;AAClC,qEAA6C;AAC7C,qDAAoC;AAEpC,MAAM,GAAG,GAAG,IAAA,iBAAO,GAAE,CAAC;AACtB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC;AAEtC,IAAA,YAAS,GAAE,CAAC;AAEZ,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,IAAI,EAAE,CAAC,CAAC;AACxB,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,oBAAU,CAAC,CAAC;AAE5B,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IACtB,GAAG,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAA;AAC3C,CAAC,CAAC,CAAC;AAEH,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE;IACnB,IAAI,GAAG,EAAE,CAAC;QACN,OAAO,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,eAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,4CAA4C,IAAI,EAAE,CAAC,CAAA;AACvG,CAAC,CAAC,CAAC;AAEH,kBAAe,GAAG,CAAC"} \ No newline at end of file diff --git a/dist/config/db.js b/dist/config/db.js new file mode 100644 index 0000000..0c19a43 --- /dev/null +++ b/dist/config/db.js @@ -0,0 +1,24 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const mongoose_1 = require("mongoose"); +const connectDB = () => __awaiter(void 0, void 0, void 0, function* () { + try { + const connection = yield (0, mongoose_1.connect)(process.env.MONGO_URI); + console.log('MongoDB connected:', connection.connection.host); + } + catch (error) { + console.error('Error connecting to MongoDB:', error.message); + process.exit(1); // Exit process with failure + } +}); +exports.default = connectDB; +//# sourceMappingURL=db.js.map \ No newline at end of file diff --git a/dist/config/db.js.map b/dist/config/db.js.map new file mode 100644 index 0000000..d8aa57f --- /dev/null +++ b/dist/config/db.js.map @@ -0,0 +1 @@ +{"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/config/db.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,uCAAmC;AAEnC,MAAM,SAAS,GAAG,GAAS,EAAE;IAC3B,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,MAAM,IAAA,kBAAO,EAAC,OAAO,CAAC,GAAG,CAAC,SAAmB,CAAC,CAAC;QAElE,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAChE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,4BAA4B;IAC/C,CAAC;AACH,CAAC,CAAA,CAAC;AAEF,kBAAe,SAAS,CAAC"} \ No newline at end of file diff --git a/dist/controllers/userController.js b/dist/controllers/userController.js new file mode 100644 index 0000000..3ff66ab --- /dev/null +++ b/dist/controllers/userController.js @@ -0,0 +1,77 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.UserController = void 0; +const userService_1 = require("../services/userService"); +const userService = new userService_1.UserService(); +class UserController { + createUser(req, res) { + return __awaiter(this, void 0, void 0, function* () { + try { + const user = yield userService.createUser(req.body); + res.status(201).json(user); + } + catch (error) { + res.status(400).json({ error: error.message }); + } + }); + } + getUser(req, res) { + return __awaiter(this, void 0, void 0, function* () { + try { + const user = yield userService.getUser(req.params.id); + if (user) { + res.status(200).json(user); + } + else { + res.status(404).json({ message: 'User not found' }); + } + } + catch (error) { + res.status(400).json({ error: error.message }); + } + }); + } + updateUser(req, res) { + return __awaiter(this, void 0, void 0, function* () { + try { + const user = yield userService.updateUser(req.params.id, req.body); + if (user) { + res.status(200).json(user); + } + else { + res.status(404).json({ message: 'User not found' }); + } + } + catch (error) { + res.status(400).json({ error: error.message }); + } + }); + } + deleteUser(req, res) { + return __awaiter(this, void 0, void 0, function* () { + try { + const user = yield userService.deleteUser(req.params.id); + if (user) { + res.status(200).json({ message: 'User deleted successfully' }); + } + else { + res.status(404).json({ message: 'User not found' }); + } + } + catch (error) { + res.status(400).json({ error: error.message }); + } + }); + } +} +exports.UserController = UserController; +//# sourceMappingURL=userController.js.map \ No newline at end of file diff --git a/dist/controllers/userController.js.map b/dist/controllers/userController.js.map new file mode 100644 index 0000000..c551360 --- /dev/null +++ b/dist/controllers/userController.js.map @@ -0,0 +1 @@ +{"version":3,"file":"userController.js","sourceRoot":"","sources":["../../src/controllers/userController.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,yDAAsD;AAEtD,MAAM,WAAW,GAAG,IAAI,yBAAW,EAAE,CAAC;AAEtC,MAAa,cAAc;IACjB,UAAU,CAAC,GAAY,EAAE,GAAa;;YACxC,IAAI,CAAC;gBACD,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACpD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACnD,CAAC;QACL,CAAC;KAAA;IAEK,OAAO,CAAC,GAAY,EAAE,GAAa;;YACrC,IAAI,CAAC;gBACD,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACtD,IAAI,IAAI,EAAE,CAAC;oBACP,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC/B,CAAC;qBAAM,CAAC;oBACJ,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC,CAAC;gBACxD,CAAC;YACL,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACnD,CAAC;QACL,CAAC;KAAA;IAEK,UAAU,CAAC,GAAY,EAAE,GAAa;;YACxC,IAAI,CAAC;gBACD,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;gBACnE,IAAI,IAAI,EAAE,CAAC;oBACP,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC/B,CAAC;qBAAM,CAAC;oBACJ,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC,CAAC;gBACxD,CAAC;YACL,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACnD,CAAC;QACL,CAAC;KAAA;IAEK,UAAU,CAAC,GAAY,EAAE,GAAa;;YACxC,IAAI,CAAC;gBACD,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACzD,IAAI,IAAI,EAAE,CAAC;oBACP,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,2BAA2B,EAAE,CAAC,CAAC;gBACnE,CAAC;qBAAM,CAAC;oBACJ,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC,CAAC;gBACxD,CAAC;YACL,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACnD,CAAC;QACL,CAAC;KAAA;CACJ;AAhDD,wCAgDC"} \ No newline at end of file diff --git a/dist/models/index.js b/dist/models/index.js new file mode 100644 index 0000000..4f46555 --- /dev/null +++ b/dist/models/index.js @@ -0,0 +1,6 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.User = void 0; +var userModel_1 = require("./userModel"); +Object.defineProperty(exports, "User", { enumerable: true, get: function () { return userModel_1.model; } }); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/models/index.js.map b/dist/models/index.js.map new file mode 100644 index 0000000..c947ebc --- /dev/null +++ b/dist/models/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/models/index.ts"],"names":[],"mappings":";;;AAAA,yCAAgE;AAAvD,iGAAA,KAAK,OAAQ"} \ No newline at end of file diff --git a/dist/models/userModel.js b/dist/models/userModel.js new file mode 100644 index 0000000..7ab72b0 --- /dev/null +++ b/dist/models/userModel.js @@ -0,0 +1,75 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +exports.model = void 0; +const mongoose_1 = __importStar(require("mongoose")); +// Create the schema +const userSchema = new mongoose_1.Schema({ + email: { + type: String, + required: true, + unique: true, + trim: true, + lowercase: true + }, + password: { + type: String, + required: true + }, + firstName: { + type: String, + required: true, + trim: true + }, + lastName: { + type: String, + trim: true + }, + status: { + type: String, + enum: ['ACTIVE', 'INACTIVE'], + default: 'ACTIVE' + }, + type: { + type: String, + enum: ['ADMIN', 'USER'], + default: 'USER' + } +}, { + timestamps: true +}); +// Create and export the model +exports.model = mongoose_1.default.model('User', userSchema); +//# sourceMappingURL=userModel.js.map \ No newline at end of file diff --git a/dist/models/userModel.js.map b/dist/models/userModel.js.map new file mode 100644 index 0000000..cb722a9 --- /dev/null +++ b/dist/models/userModel.js.map @@ -0,0 +1 @@ +{"version":3,"file":"userModel.js","sourceRoot":"","sources":["../../src/models/userModel.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qDAAsD;AActD,oBAAoB;AACpB,MAAM,UAAU,GAAG,IAAI,iBAAM,CAAY;IACrC,KAAK,EAAE;QACH,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,IAAI;QACd,MAAM,EAAE,IAAI;QACZ,IAAI,EAAE,IAAI;QACV,SAAS,EAAE,IAAI;KAClB;IACD,QAAQ,EAAE;QACN,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,IAAI;KACjB;IACD,SAAS,EAAE;QACP,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,IAAI;QACd,IAAI,EAAE,IAAI;KACb;IACD,QAAQ,EAAE;QACN,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,IAAI;KACb;IACD,MAAM,EAAE;QACJ,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC;QAC5B,OAAO,EAAE,QAAQ;KACpB;IACD,IAAI,EAAE;QACF,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC;QACvB,OAAO,EAAE,MAAM;KAClB;CACJ,EAAE;IACC,UAAU,EAAE,IAAI;CACnB,CAAC,CAAC;AAEH,8BAA8B;AACjB,QAAA,KAAK,GAAG,kBAAQ,CAAC,KAAK,CAAY,MAAM,EAAE,UAAU,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/routes/userRoutes.js b/dist/routes/userRoutes.js new file mode 100644 index 0000000..901c245 --- /dev/null +++ b/dist/routes/userRoutes.js @@ -0,0 +1,12 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const express_1 = require("express"); +const userController_1 = require("../controllers/userController"); +const router = (0, express_1.Router)(); +const userController = new userController_1.UserController(); +router.post('/users', userController.createUser); +router.get('/users/:id', userController.getUser); +router.put('/users/:id', userController.updateUser); +router.delete('/users/:id', userController.deleteUser); +exports.default = router; +//# sourceMappingURL=userRoutes.js.map \ No newline at end of file diff --git a/dist/routes/userRoutes.js.map b/dist/routes/userRoutes.js.map new file mode 100644 index 0000000..757236b --- /dev/null +++ b/dist/routes/userRoutes.js.map @@ -0,0 +1 @@ +{"version":3,"file":"userRoutes.js","sourceRoot":"","sources":["../../src/routes/userRoutes.ts"],"names":[],"mappings":";;AAAA,qCAAiC;AACjC,kEAA+D;AAE/D,MAAM,MAAM,GAAG,IAAA,gBAAM,GAAE,CAAC;AACxB,MAAM,cAAc,GAAG,IAAI,+BAAc,EAAE,CAAC;AAE5C,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;AACjD,MAAM,CAAC,GAAG,CAAC,YAAY,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC;AACjD,MAAM,CAAC,GAAG,CAAC,YAAY,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;AACpD,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;AAEvD,kBAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/dist/services/userService.js b/dist/services/userService.js new file mode 100644 index 0000000..75e1fcf --- /dev/null +++ b/dist/services/userService.js @@ -0,0 +1,38 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.UserService = void 0; +const models_1 = require("../models"); +class UserService { + createUser(data) { + return __awaiter(this, void 0, void 0, function* () { + const user = new models_1.User(data); + return yield user.save(); + }); + } + getUser(id) { + return __awaiter(this, void 0, void 0, function* () { + return yield models_1.User.findById(id).exec(); + }); + } + updateUser(id, data) { + return __awaiter(this, void 0, void 0, function* () { + return yield models_1.User.findByIdAndUpdate(id, data, { new: true }).exec(); + }); + } + deleteUser(id) { + return __awaiter(this, void 0, void 0, function* () { + return yield models_1.User.findByIdAndDelete(id).exec(); + }); + } +} +exports.UserService = UserService; +//# sourceMappingURL=userService.js.map \ No newline at end of file diff --git a/dist/services/userService.js.map b/dist/services/userService.js.map new file mode 100644 index 0000000..7e62260 --- /dev/null +++ b/dist/services/userService.js.map @@ -0,0 +1 @@ +{"version":3,"file":"userService.js","sourceRoot":"","sources":["../../src/services/userService.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,sCAAwC;AAExC,MAAa,WAAW;IACd,UAAU,CAAC,IAAoB;;YACjC,MAAM,IAAI,GAAG,IAAI,aAAI,CAAC,IAAI,CAAC,CAAC;YAC5B,OAAO,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAC7B,CAAC;KAAA;IAEK,OAAO,CAAC,EAAU;;YACpB,OAAO,MAAM,aAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC1C,CAAC;KAAA;IAEK,UAAU,CAAC,EAAU,EAAE,IAAoB;;YAC7C,OAAO,MAAM,aAAI,CAAC,iBAAiB,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACxE,CAAC;KAAA;IAEK,UAAU,CAAC,EAAU;;YACvB,OAAO,MAAM,aAAI,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACnD,CAAC;KAAA;CACJ;AAjBD,kCAiBC"} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index ba94052..c399124 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "ISC", "dependencies": { "express": "^5.0.1", + "mongoose": "^8.12.1", "winston": "^3.17.0" }, "devDependencies": { @@ -258,6 +259,15 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.2.0.tgz", + "integrity": "sha512-+ywrb0AqkfaYuhHs6LxKWgqbh3I72EpEgESCw37o+9qPx9WTCkgDm2B+eMrwehGtHBWHFU4GXvnSCNiFhhausg==", + "license": "MIT", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -424,6 +434,21 @@ "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", "license": "MIT" }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==", + "license": "MIT" + }, + "node_modules/@types/whatwg-url": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", + "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", + "license": "MIT", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.26.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.26.1.tgz", @@ -778,6 +803,15 @@ "node": ">=8" } }, + "node_modules/bson": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.3.tgz", + "integrity": "sha512-MTxGsqgYTwfshYWTRdmZRC+M7FnG1b4y7RO7p2k3X24Wq0yv1m77Wsj0BzlPzd/IowgESfsruQCUToa7vbOpPQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=16.20.1" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -1800,6 +1834,15 @@ "dev": true, "license": "MIT" }, + "node_modules/kareem": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", + "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==", + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -1888,6 +1931,12 @@ "node": ">= 0.8" } }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "license": "MIT" + }, "node_modules/merge-descriptors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", @@ -1967,6 +2016,105 @@ "node": "*" } }, + "node_modules/mongodb": { + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.14.2.tgz", + "integrity": "sha512-kMEHNo0F3P6QKDq17zcDuPeaywK/YaJVCEQRzPF3TOM/Bl9MFg64YE5Tu7ifj37qZJMhwU1tl2Ioivws5gRG5Q==", + "license": "Apache-2.0", + "dependencies": { + "@mongodb-js/saslprep": "^1.1.9", + "bson": "^6.10.3", + "mongodb-connection-string-url": "^3.0.0" + }, + "engines": { + "node": ">=16.20.1" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0 || ^2.0.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz", + "integrity": "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==", + "license": "Apache-2.0", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^14.1.0 || ^13.0.0" + } + }, + "node_modules/mongoose": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.12.1.tgz", + "integrity": "sha512-UW22y8QFVYmrb36hm8cGncfn4ARc/XsYWQwRTaj0gxtQk1rDuhzDO1eBantS+hTTatfAIS96LlRCJrcNHvW5+Q==", + "license": "MIT", + "dependencies": { + "bson": "^6.10.3", + "kareem": "2.6.3", + "mongodb": "~6.14.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "17.1.3" + }, + "engines": { + "node": ">=16.20.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "license": "MIT", + "dependencies": { + "debug": "4.x" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -2172,7 +2320,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -2540,6 +2687,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/sift": { + "version": "17.1.3", + "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz", + "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==", + "license": "MIT" + }, "node_modules/simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", @@ -2549,6 +2702,15 @@ "is-arrayish": "^0.3.1" } }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "license": "MIT", + "dependencies": { + "memory-pager": "^1.0.2" + } + }, "node_modules/stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", @@ -2630,6 +2792,18 @@ "node": ">=0.6" } }, + "node_modules/tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/triple-beam": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", @@ -2766,6 +2940,28 @@ "node": ">= 0.8" } }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.1.1.tgz", + "integrity": "sha512-mDGf9diDad/giZ/Sm9Xi2YcyzaFpbdLpJPr+E9fSkyQ7KpQD4SdFcugkRQYzhmfI4KeV4Qpnn2sKPdo+kmsgRQ==", + "license": "MIT", + "dependencies": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index e9a27b9..a45089f 100644 --- a/package.json +++ b/package.json @@ -4,11 +4,12 @@ "description": "", "main": "index.js", "scripts": { - "start": "tsc && NODE_ENV=development node dist/app.js", + "start": "tsc && NODE_ENV=development node --env-file=.env.local dist/app.js", "dev": "tsc -w & NODE_ENV=development node --env-file=.env.local --watch dist/app.js", "test": "echo \"Error: no test specified\"" }, "author": "Mudit Khandelwal (code-storm)", + "keywords": ["node", "typescript", "express", "mongoose", "winston"], "license": "ISC", "devDependencies": { "@eslint/js": "^9.22.0", @@ -20,6 +21,7 @@ }, "dependencies": { "express": "^5.0.1", + "mongoose": "^8.12.1", "winston": "^3.17.0" } } diff --git a/samplecurl.txt b/samplecurl.txt new file mode 100644 index 0000000..75f671c --- /dev/null +++ b/samplecurl.txt @@ -0,0 +1,8 @@ +curl --location 'http://localhost:4000/api/users' \ +--header 'Content-Type: application/json' \ +--data-raw '{ + "firstName": "Don", + "lastName": "Draper", + "email": "don@test.com", + "password": "Testing123" +}' \ No newline at end of file diff --git a/src/app.ts b/src/app.ts index c18f4ad..0af8ec6 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,8 +1,16 @@ import express from "express"; import { logger } from "./logger"; +import userRoutes from './routes/userRoutes'; +import connectDB from "./config/db"; const app = express(); const port = process.env.PORT || 3000; + +connectDB(); + +app.use(express.json()); +app.use('/api', userRoutes); + app.get('/', (req, res) => { res.send('GET request is working here') }); @@ -12,4 +20,6 @@ app.listen(port, err => { return console.error(err); } return logger.info(`${process.env.NODE_ENV || ''} server is listening on http://localhost:${port}`) -}); \ No newline at end of file +}); + +export default app; \ No newline at end of file diff --git a/src/config/db.ts b/src/config/db.ts new file mode 100644 index 0000000..615d732 --- /dev/null +++ b/src/config/db.ts @@ -0,0 +1,14 @@ +import { connect } from 'mongoose'; + +const connectDB = async () => { + try { + const connection = await connect(process.env.MONGO_URI as string); + + console.log('MongoDB connected:', connection.connection.host); + } catch (error) { + console.error('Error connecting to MongoDB:', error.message); + process.exit(1); // Exit process with failure + } +}; + +export default connectDB; \ No newline at end of file diff --git a/src/controllers/userController.ts b/src/controllers/userController.ts new file mode 100644 index 0000000..78d87ee --- /dev/null +++ b/src/controllers/userController.ts @@ -0,0 +1,54 @@ +import { Request, Response } from 'express'; +import { UserService } from '../services/userService'; + +const userService = new UserService(); + +export class UserController { + async createUser(req: Request, res: Response): Promise { + try { + const user = await userService.createUser(req.body); + res.status(201).json(user); + } catch (error) { + res.status(400).json({ error: error.message }); + } + } + + async getUser(req: Request, res: Response): Promise { + try { + const user = await userService.getUser(req.params.id); + if (user) { + res.status(200).json(user); + } else { + res.status(404).json({ message: 'User not found' }); + } + } catch (error) { + res.status(400).json({ error: error.message }); + } + } + + async updateUser(req: Request, res: Response): Promise { + try { + const user = await userService.updateUser(req.params.id, req.body); + if (user) { + res.status(200).json(user); + } else { + res.status(404).json({ message: 'User not found' }); + } + } catch (error) { + res.status(400).json({ error: error.message }); + } + } + + async deleteUser(req: Request, res: Response): Promise { + try { + const user = await userService.deleteUser(req.params.id); + if (user) { + res.status(200).json({ message: 'User deleted successfully' }); + } else { + res.status(404).json({ message: 'User not found' }); + } + } catch (error) { + res.status(400).json({ error: error.message }); + } + } +} diff --git a/src/models/index.ts b/src/models/index.ts new file mode 100644 index 0000000..d02fe91 --- /dev/null +++ b/src/models/index.ts @@ -0,0 +1 @@ +export { model as User, IDocument as IUser } from "./userModel"; diff --git a/src/models/userModel.ts b/src/models/userModel.ts new file mode 100644 index 0000000..697857f --- /dev/null +++ b/src/models/userModel.ts @@ -0,0 +1,52 @@ +import mongoose, { Document, Schema } from 'mongoose'; + +// Interface to define user document structure +export interface IDocument extends Document { + email: string; + password: string; + firstName: string; + lastName: string; + status: "ACTIVE" | "INACTIVE"; + type: "ADMIN" | "USER"; + createdAt: Date; + updatedAt: Date; +} + +// Create the schema +const userSchema = new Schema({ + email: { + type: String, + required: true, + unique: true, + trim: true, + lowercase: true + }, + password: { + type: String, + required: true + }, + firstName: { + type: String, + required: true, + trim: true + }, + lastName: { + type: String, + trim: true + }, + status: { + type: String, + enum: ['ACTIVE', 'INACTIVE'], + default: 'ACTIVE' + }, + type: { + type: String, + enum: ['ADMIN', 'USER'], + default: 'USER' + } +}, { + timestamps: true +}); + +// Create and export the model +export const model = mongoose.model('User', userSchema); \ No newline at end of file diff --git a/src/routes/userRoutes.ts b/src/routes/userRoutes.ts new file mode 100644 index 0000000..6d06571 --- /dev/null +++ b/src/routes/userRoutes.ts @@ -0,0 +1,12 @@ +import { Router } from 'express'; +import { UserController } from '../controllers/userController'; + +const router = Router(); +const userController = new UserController(); + +router.post('/users', userController.createUser); +router.get('/users/:id', userController.getUser); +router.put('/users/:id', userController.updateUser); +router.delete('/users/:id', userController.deleteUser); + +export default router; diff --git a/src/services/userService.ts b/src/services/userService.ts new file mode 100644 index 0000000..94b62fa --- /dev/null +++ b/src/services/userService.ts @@ -0,0 +1,20 @@ +import { IUser, User } from '../models'; + +export class UserService { + async createUser(data: Partial): Promise { + const user = new User(data); + return await user.save(); + } + + async getUser(id: string): Promise { + return await User.findById(id).exec(); + } + + async updateUser(id: string, data: Partial): Promise { + return await User.findByIdAndUpdate(id, data, { new: true }).exec(); + } + + async deleteUser(id: string): Promise { + return await User.findByIdAndDelete(id).exec(); + } +}