diff --git a/package-lock.json b/package-lock.json index dfaa101..750c2db 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,8 +8,18 @@ "name": "mongodb-ts", "version": "1.0.0", "license": "ISC", + "dependencies": { + "cors": "^2.8.5", + "dotenv": "^16.5.0", + "mongoose": "^8.15.2", + "morgan": "^1.10.0", + "multer": "^2.0.1" + }, "devDependencies": { + "@types/cors": "^2.8.19", "@types/express": "^5.0.3", + "@types/morgan": "^1.9.10", + "@types/multer": "^1.4.13", "@types/node": "^24.0.1", "express": "^5.1.0", "ts-node": "^10.9.2", @@ -53,6 +63,15 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.3.0.tgz", + "integrity": "sha512-zlayKCsIjYb7/IdfqxorK5+xUMyi4vOKcFy10wKJYc63NSdKI8mNME+uJqfatkPmOSMMUiojrL58IePKBm3gvQ==", + "license": "MIT", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, "node_modules/@tsconfig/node10": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", @@ -96,6 +115,16 @@ "@types/node": "*" } }, + "node_modules/@types/cors": { + "version": "2.8.19", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", + "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/express": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.3.tgz", @@ -131,6 +160,26 @@ "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", "dev": true }, + "node_modules/@types/morgan": { + "version": "1.9.10", + "resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.10.tgz", + "integrity": "sha512-sS4A1zheMvsADRVfT0lYbJ4S9lmsey8Zo2F7cnbYjWHP67Q0AwMYuuzLlkIM2N8gAbb9cubhIVFwcIN2XyYCkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/multer": { + "version": "1.4.13", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.13.tgz", + "integrity": "sha512-bhhdtPw7JqCiEfC9Jimx5LqX9BDIPJEh2q/fQ4bqbBPtyEZYr3cvF22NwG0DmPZNYA0CAf2CnqDB4KIGGpJcaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, "node_modules/@types/node": { "version": "24.0.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.1.tgz", @@ -173,6 +222,21 @@ "@types/send": "*" } }, + "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/accepts": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", @@ -210,12 +274,36 @@ "node": ">=0.4.0" } }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", + "license": "MIT" + }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, "node_modules/body-parser": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", @@ -236,6 +324,32 @@ "node": ">=18" } }, + "node_modules/bson": { + "version": "6.10.4", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.4.tgz", + "integrity": "sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==", + "license": "Apache-2.0", + "engines": { + "node": ">=16.20.1" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -274,6 +388,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, "node_modules/content-disposition": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", @@ -313,6 +442,19 @@ "node": ">=6.6.0" } }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -323,7 +465,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "dev": true, "dependencies": { "ms": "^2.1.3" }, @@ -340,7 +481,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, "engines": { "node": ">= 0.8" } @@ -354,6 +494,18 @@ "node": ">=0.3.1" } }, + "node_modules/dotenv": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", + "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -371,8 +523,7 @@ "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/encodeurl": { "version": "2.0.0", @@ -627,8 +778,7 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/ipaddr.js": { "version": "1.9.1", @@ -645,6 +795,15 @@ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", "dev": true }, + "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/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -669,6 +828,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", @@ -702,11 +867,234 @@ "node": ">= 0.6" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mongodb": { + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.16.0.tgz", + "integrity": "sha512-D1PNcdT0y4Grhou5Zi/qgipZOYeWrhLEpk33n3nm6LGtz61jvO88WlrWCK/bigMjpnOdAUKKQwsGIl0NtWMyYw==", + "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.15.2", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.15.2.tgz", + "integrity": "sha512-GLwghI2dS/n5BTBljspF4+FsCEBeHgnMQyX8GloYkLkl+MKljKkjcP9DhLr47Yod2RO1RCr4vZ3evUZAyuoILw==", + "license": "MIT", + "dependencies": { + "bson": "^6.10.3", + "kareem": "2.6.3", + "mongodb": "~6.16.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/morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "license": "MIT", + "dependencies": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/morgan/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/morgan/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/morgan/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "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", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/multer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.1.tgz", + "integrity": "sha512-Ug8bXeTIUlxurg8xLTEskKShvcKDZALo1THEX5E41pYCD2sCVub5/kIRIGqWNoqV6szyLyQKV6mD4QUrWE5GCQ==", + "license": "MIT", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.6.0", + "concat-stream": "^2.0.0", + "mkdirp": "^0.5.6", + "object-assign": "^4.1.1", + "type-is": "^1.6.18", + "xtend": "^4.0.2" + }, + "engines": { + "node": ">= 10.16.0" + } + }, + "node_modules/multer/node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } }, "node_modules/negotiator": { "version": "1.0.0", @@ -717,6 +1105,15 @@ "node": ">= 0.6" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", @@ -741,6 +1138,15 @@ "node": ">= 0.8" } }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -781,6 +1187,15 @@ "node": ">= 0.10" } }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/qs": { "version": "6.14.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", @@ -820,6 +1235,20 @@ "node": ">= 0.8" } }, + "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/router": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", @@ -840,7 +1269,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -977,6 +1405,21 @@ "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/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/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", @@ -986,6 +1429,23 @@ "node": ">= 0.8" } }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "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/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -995,6 +1455,18 @@ "node": ">=0.6" } }, + "node_modules/tr46": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -1052,6 +1524,12 @@ "node": ">= 0.6" } }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "license": "MIT" + }, "node_modules/typescript": { "version": "5.8.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", @@ -1080,6 +1558,12 @@ "node": ">= 0.8" } }, + "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/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -1090,17 +1574,47 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true, "engines": { "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.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "license": "MIT", + "dependencies": { + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", diff --git a/package.json b/package.json index 947f7ee..d4e0d41 100644 --- a/package.json +++ b/package.json @@ -4,17 +4,27 @@ "description": "", "main": "index.js", "scripts": { - "start": "nodemon src/app.ts", + "start": "nodemon src/server.ts", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { + "@types/cors": "^2.8.19", "@types/express": "^5.0.3", + "@types/morgan": "^1.9.10", + "@types/multer": "^1.4.13", "@types/node": "^24.0.1", "express": "^5.1.0", "ts-node": "^10.9.2", "typescript": "^5.8.3" + }, + "dependencies": { + "cors": "^2.8.5", + "dotenv": "^16.5.0", + "mongoose": "^8.15.2", + "morgan": "^1.10.0", + "multer": "^2.0.1" } } diff --git a/src/account.ts b/src/account.ts index e077a5b..c117dee 100644 --- a/src/account.ts +++ b/src/account.ts @@ -1,17 +1,17 @@ export const accounts = [ - { - id: 1, - username: "Omar", - funds: 30, - }, - { - id: 2, - username: "Zainab", - funds: 0, - }, - { - id: 3, - username: "Salwa", - funds: 100, - }, -]; \ No newline at end of file + { + id: 1, + username: "Omar", + funds: 30, + }, + { + id: 2, + username: "Zainab", + funds: 0, + }, + { + id: 3, + username: "Salwa", + funds: 100, + }, +]; diff --git a/src/api/accounts/accounts.controller.ts b/src/api/accounts/accounts.controller.ts index 0073135..6bbe1c5 100644 --- a/src/api/accounts/accounts.controller.ts +++ b/src/api/accounts/accounts.controller.ts @@ -1,48 +1,141 @@ -import { Request, Response } from 'express'; -import { accounts } from '../../account'; +import { NextFunction, Request, Response } from "express"; +import { accounts } from "../../account"; +import Account from "../../model/Account"; -export const accountCreate = (req: Request, res: Response) => { - const id = accounts[accounts.length - 1].id + 1; - const newAccount = { ...req.body, funds: 0, id }; - accounts.push(newAccount); - res.status(201).json(newAccount); +//creating new account +export const accountCreate = async ( + req: Request, + res: Response, + next: NextFunction +) => { + // const id = accounts[accounts.length - 1].id + 1; + // const newAccount = { ...req.body, funds: 0, id }; + // accounts.push(newAccount); + // res.status(201).json(newAccount); + try { + const { username, funds, image } = req.body; + // console.log( + // "Creating account with username:", + // username, + // "and funds:", + // funds + // ); + let imagePath; + if (req.file) { + imagePath = req.file?.path; + } + const newAcc = await Account.create({ username, funds, image: imagePath }); // Account is my created model / image(key): imagePath(value) + res.status(201).json(newAcc); + } catch (error) { + // res.status(500).json({ message: "Error creating an account.." }); + next(error); // Pass the error to the next middleware (error handler) + } }; - -export const accountDelete = (req: Request, res: Response) => { +// Deleting an account +export const accountDelete = async ( + req: Request, + res: Response, + next: NextFunction +) => { + // const foundAccount = accounts.find((account) => account.id === +accountId); + // if (foundAccount) { + // let newAccounts = accounts.filter((account) => account.id !== +accountId); + // res.status(204).end(); + // } else { + // res.status(404).json({ message: "Account not found" }); + // } + try { const { accountId } = req.params; - const foundAccount = accounts.find((account) => account.id === +accountId); - if (foundAccount) { - let newAccounts = accounts.filter((account) => account.id !== +accountId); - res.status(204).end(); + const foundACCFromDB = await Account.findByIdAndDelete(accountId); + + if (foundACCFromDB) { + res.status(204).end(); } else { - res.status(404).json({ message: 'Account not found' }); + res.status(404).json({ message: "Account not found" }); } + } catch (error) { + // res.status(500).json({ message: "Error deleting account..." }); + next(error); + } }; -export const accountUpdate = (req: Request, res: Response) => { - const { accountId } = req.params; - const foundAccount = accounts.find((account) => account.id === +accountId); - if (foundAccount) { - foundAccount.funds = req.body.funds; - res.status(204).end(); - } else { - res.status(404).json({ message: 'Account not found' }); +// Updating an account +export const accountUpdate = async ( + req: Request, + res: Response, + next: NextFunction +) => { + const { accountId } = req.params; + const { username, funds } = req.body; + // const foundAccount = accounts.find((account) => account.id === +accountId); + const updateAccInDB = await Account.findByIdAndUpdate(accountId, { + username, + funds, + }); + try { + if (updateAccInDB) { + res.status(204).end(); } + } catch (error) { + next(error); + } + // if (updateAccInDB) { + // res.status(204).end(); + // } else { + // res.status(404).json({ message: "Account not found, can't update" }); + // } }; - -export const accountsGet = (req: Request, res: Response) => { - res.json(accounts); +// get all accounts from the database +export const accountsGet = async ( + req: Request, + res: Response, + next: NextFunction +) => { + try { + const accountsFromDB = await Account.find(); + res.status(200).json(accountsFromDB); + } catch (error) { + // res.status(500).json({ message: "Error fetching accounts..." }); + next(error); + } +}; +// get one account by username +export const getAccountByUsername = async (req: Request, res: Response) => { + const { username } = req.params; + // const foundAccount = accounts.find( + // (account) => account.username === username + // ); + const foundAccByUsername = await Account.findOne({ username }); + if (req.query.currency === "usd" && foundAccByUsername) { + const accountInUsd = { + ...foundAccByUsername, + funds: foundAccByUsername.funds * 3.31, + }; + res.status(201).json(accountInUsd); + } else { + res.status(201).json(foundAccByUsername); + } }; -export const getAccountByUsername = (req: Request, res: Response) => { - const { username } = req.params; - const foundAccount = accounts.find( - (account) => account.username === username - ); - if (req.query.currency === 'usd' && foundAccount) { - const accountInUsd = { ...foundAccount, funds: foundAccount.funds * 3.31 }; - res.status(201).json(accountInUsd); - } else { - res.status(201).json(foundAccount); - } -}; \ No newline at end of file +// get one account by username, abd check for amount above 3000 +// export const getAccByUsernameAmount = async (req: Request, res: Response) => { +// const { username } = req.params; +// // const foundAccount = accounts.find( +// // (account) => account.username === username +// // ); +// const foundAccByUsername = await Account.find({ username }); // this is an array, find a way to just grap the users with the correct condition +// // check +// if ( +// foundAccByUsername && +// Number(req.query.amount) <= foundAccByUsername?.funds +// ) { +// const accountWithCorrectAmount = { +// username: foundAccByUsername.username, +// funds: foundAccByUsername.funds, +// }; +// res.status(201).json(accountWithCorrectAmount); +// } else { +// // res.status(201).json(foundAccByUsername); +// res.status(500).json({ message: "Error fetching accounts..." }); +// } +// }; diff --git a/src/api/accounts/accounts.routes.ts b/src/api/accounts/accounts.routes.ts index 9874aa1..5af3a19 100644 --- a/src/api/accounts/accounts.routes.ts +++ b/src/api/accounts/accounts.routes.ts @@ -1,13 +1,24 @@ -import express from 'express'; +import express from "express"; const accountsRouter = express.Router(); -import { accountsGet, accountUpdate, accountDelete, accountCreate, getAccountByUsername } from './accounts.controller'; +import { + accountsGet, + accountUpdate, + accountDelete, + accountCreate, + getAccountByUsername, + // getAccByUsernameAmount, +} from "./accounts.controller"; +import upload from "../../middlewares/multer"; -accountsRouter.get('/', accountsGet); -accountsRouter.get('/:username', getAccountByUsername); -accountsRouter.post('/', accountCreate); +accountsRouter.get("/", accountsGet); +accountsRouter.get("/:username", getAccountByUsername); +accountsRouter.post("/", upload.single("image"), accountCreate); // multer middleware used here -accountsRouter.delete('/:accountId', accountDelete); +accountsRouter.delete("/:accountId", accountDelete); -accountsRouter.put('/:accountId', accountUpdate); +accountsRouter.put("/:accountId", accountUpdate); -export default accountsRouter; \ No newline at end of file +// new route created +// accountsRouter.get("/vip", getAccByUsernameAmount); + +export default accountsRouter; diff --git a/src/app.ts b/src/app.ts index b151d8d..0933526 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,12 +1,32 @@ import express from "express"; +import { Request, Response, NextFunction } from "express"; +import morgan from "morgan"; +import cors from "cors"; import accountsRouter from "./api/accounts/accounts.routes"; +import notFoundHandler from "./middlewares/NotFound"; +import errorHandler from "./middlewares/ErrorHandler"; +import path from "path"; const app = express(); -const PORT = 8000; -app.use(express.json()); -app.use("/accounts", accountsRouter); +app.use((req: Request, res: Response, next: NextFunction) => { + console.log(new Date().toLocaleString()); + next(); +}); +app.use(morgan("dev")); // Morgan is a thid party logging middleware, it logs every request to the console +app.use(cors()); // CORS is a middleware that allows cross-origin requests, it is used to allow requests from different origins (domains) -app.listen(PORT, () => { - console.log(`Server is running on port ${PORT}`); -}); \ No newline at end of file +app.use(express.json()); // Middleware to parse JSON bodies, every single request with body has to be JSon +// all middleware must be placed before the routes +app.use("/accounts", accountsRouter); // app.use is app level middleware +app.use("./src/uploads", express.static(path.join(__dirname, "uploads"))); // this middleware will fix the image path so we can view it in a browser, joining the root dir with uploads + +// ----------- 404 error handler middleware and plug in controllers +app.use(notFoundHandler); + +// ----------- 500 error handler middleware and plug in controllers +app.use(errorHandler); + +export default app; + +// app.ts is where we place middlewares, routes, and other configurations for the Express application. diff --git a/src/middlewares/ErrorHandler.ts b/src/middlewares/ErrorHandler.ts new file mode 100644 index 0000000..68ae92c --- /dev/null +++ b/src/middlewares/ErrorHandler.ts @@ -0,0 +1,15 @@ +import { NextFunction, Request, Response } from "express"; + +const errorHandler = ( + err: any, + req: Request, + res: Response, + next: NextFunction +) => { + console.log(err); + res + .status(err.status || 500) + .json(`something broke ${err} at path: ${req.path}`); +}; + +export default errorHandler; diff --git a/src/middlewares/NotFound.ts b/src/middlewares/NotFound.ts new file mode 100644 index 0000000..8156be7 --- /dev/null +++ b/src/middlewares/NotFound.ts @@ -0,0 +1,13 @@ +import { NextFunction, Request, Response } from "express"; + +const notFoundHandler = ( + err: any, + req: Request, + res: Response, + next: NextFunction +) => { + console.log(err); + res.status(404).json({ message: `Not found at path: ${req.path}` }); +}; + +export default notFoundHandler; diff --git a/src/middlewares/multer.ts b/src/middlewares/multer.ts new file mode 100644 index 0000000..bbf5fe4 --- /dev/null +++ b/src/middlewares/multer.ts @@ -0,0 +1,47 @@ +import { Request } from "express"; +import multer from "multer"; +import path from "path"; + +// this middleware is router lever, why? because i only need image/files upload in certain endpoints +// this will store the uploaded files in the /tmp/my-uploads directory +// diskstorage, will store files on my local machine as files +const storage = multer.diskStorage({ + destination: function (req, file, cb) { + cb(null, "./src/uploads"); // this is the directory where the files will be stored; + }, + filename: function (req, file, cb) { + // this will make sure that the file name is unique, to avoid naming clashes + const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() * 1e9); + cb(null, file.fieldname + "-" + uniqueSuffix + "-" + file.originalname); + }, +}); +// const fileFilter = (req: Request, file: Express.Multer.File, cb: any) => { +// // The function should call `cb` with a boolean +// // to indicate if the file should be accepted + +// // To accept only .png files +// if (file.mimetype === "image/png") { +// cb(null, true); // this will accept the file? +// } else { +// cb(Error("only .PNG files accepted"), false); +// } +// }; +// task: restrict the user to .png file type +const upload = multer({ + storage: storage, + fileFilter: (req, file, cb) => { + const allowedTypes = /jpg|png/; + const extValid = allowedTypes.test( + path.extname(file.originalname).toLowerCase() + ); + const mimeValid = allowedTypes.test(file.mimetype); + + if (extValid && mimeValid) { + cb(null, true); // Accept the file + } else { + cb(new Error("Only .jpg and .png files are allowed!") as any, false); // Reject the file + } + }, +}); + +export default upload; diff --git a/src/model/Account.ts b/src/model/Account.ts new file mode 100644 index 0000000..af6fd67 --- /dev/null +++ b/src/model/Account.ts @@ -0,0 +1,11 @@ +import { model, Schema } from "mongoose"; + +const accountSchema = new Schema({ + username: { type: String, required: true }, + funds: { type: Number, default: 0 }, + // timeStamp: { timestamps: true }, + image: { type: String }, +}); +const Account = model("Account", accountSchema); + +export default Account; diff --git a/src/server.ts b/src/server.ts new file mode 100644 index 0000000..143ed84 --- /dev/null +++ b/src/server.ts @@ -0,0 +1,21 @@ +import app from "./app"; +import mongoose from "mongoose"; +import dotenv from "dotenv"; + +// this will expose the .env file to my server +dotenv.config(); + +const connectDB = async () => { + // this url needs to be secured + try { + const connection = await mongoose.connect(process.env.MONGODB_URI || ""); + console.log("connected to mongoDB:"); + } catch (error) { + console.error("Error connecting to MongoDB:", error); + } +}; +const PORT = 8000; +connectDB(); +app.listen(PORT, () => { + console.log(`Server running at http://localhost:${PORT}`); +}); diff --git a/src/uploads/image-1750174357236-850435691-poster2.jpg b/src/uploads/image-1750174357236-850435691-poster2.jpg new file mode 100644 index 0000000..48fb7de Binary files /dev/null and b/src/uploads/image-1750174357236-850435691-poster2.jpg differ diff --git a/src/uploads/image-1750175768527-822762102-poster2.jpg b/src/uploads/image-1750175768527-822762102-poster2.jpg new file mode 100644 index 0000000..48fb7de Binary files /dev/null and b/src/uploads/image-1750175768527-822762102-poster2.jpg differ diff --git a/src/uploads/image-1750175821422-410667495-poster2.jpg b/src/uploads/image-1750175821422-410667495-poster2.jpg new file mode 100644 index 0000000..48fb7de Binary files /dev/null and b/src/uploads/image-1750175821422-410667495-poster2.jpg differ diff --git a/src/uploads/image-1750175900211-918338537-poster2.jpg b/src/uploads/image-1750175900211-918338537-poster2.jpg new file mode 100644 index 0000000..48fb7de Binary files /dev/null and b/src/uploads/image-1750175900211-918338537-poster2.jpg differ diff --git a/src/uploads/image-1750178019419-976792112-poster2.jpg b/src/uploads/image-1750178019419-976792112-poster2.jpg new file mode 100644 index 0000000..48fb7de Binary files /dev/null and b/src/uploads/image-1750178019419-976792112-poster2.jpg differ diff --git a/src/uploads/image-1750178077246-26288160-poster2.jpg b/src/uploads/image-1750178077246-26288160-poster2.jpg new file mode 100644 index 0000000..48fb7de Binary files /dev/null and b/src/uploads/image-1750178077246-26288160-poster2.jpg differ diff --git a/src/uploads/image-1750178083275-457921125-poster2.jpg b/src/uploads/image-1750178083275-457921125-poster2.jpg new file mode 100644 index 0000000..48fb7de Binary files /dev/null and b/src/uploads/image-1750178083275-457921125-poster2.jpg differ diff --git a/src/uploads/image-1750178186145-975096343-poster2.jpg b/src/uploads/image-1750178186145-975096343-poster2.jpg new file mode 100644 index 0000000..48fb7de Binary files /dev/null and b/src/uploads/image-1750178186145-975096343-poster2.jpg differ diff --git a/src/uploads/image-1750178190296-163838087-poster2.jpg b/src/uploads/image-1750178190296-163838087-poster2.jpg new file mode 100644 index 0000000..48fb7de Binary files /dev/null and b/src/uploads/image-1750178190296-163838087-poster2.jpg differ diff --git a/src/uploads/image-1750178219228-614271549-poster2.jpg b/src/uploads/image-1750178219228-614271549-poster2.jpg new file mode 100644 index 0000000..48fb7de Binary files /dev/null and b/src/uploads/image-1750178219228-614271549-poster2.jpg differ diff --git a/src/uploads/image-1750178257790-764723223-poster2.jpg b/src/uploads/image-1750178257790-764723223-poster2.jpg new file mode 100644 index 0000000..48fb7de Binary files /dev/null and b/src/uploads/image-1750178257790-764723223-poster2.jpg differ diff --git a/src/uploads/image-1750178423139-505360777-poster2.jpg b/src/uploads/image-1750178423139-505360777-poster2.jpg new file mode 100644 index 0000000..48fb7de Binary files /dev/null and b/src/uploads/image-1750178423139-505360777-poster2.jpg differ diff --git a/src/uploads/image-1750178480537-36859301-poster2.jpg b/src/uploads/image-1750178480537-36859301-poster2.jpg new file mode 100644 index 0000000..48fb7de Binary files /dev/null and b/src/uploads/image-1750178480537-36859301-poster2.jpg differ diff --git a/src/uploads/image-1750178711953-697831444-poster2.jpg b/src/uploads/image-1750178711953-697831444-poster2.jpg new file mode 100644 index 0000000..48fb7de Binary files /dev/null and b/src/uploads/image-1750178711953-697831444-poster2.jpg differ diff --git a/src/uploads/image-1750179763392-233679936-Capture.PNG b/src/uploads/image-1750179763392-233679936-Capture.PNG new file mode 100644 index 0000000..0926389 Binary files /dev/null and b/src/uploads/image-1750179763392-233679936-Capture.PNG differ