wip
@@ -96,3 +96,10 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
||||
## License
|
||||
|
||||
Nest is [MIT licensed](https://github.com/nestjs/nest/blob/master/LICENSE).
|
||||
|
||||
|
||||
## TODO
|
||||
|
||||
-fix picture upload
|
||||
-implement picture loader
|
||||
-use leaflet for map implementation
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
BIN
assets/uploads/profileImage-1755863111419-288148730.png
Normal file
|
After Width: | Height: | Size: 440 KiB |
BIN
assets/uploads/profileImage-1755863470216-89904139.png
Normal file
|
After Width: | Height: | Size: 440 KiB |
BIN
assets/uploads/profileImage-1755863741914-819946356.png
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
assets/uploads/profileImage-1755875957454-185748963.png
Normal file
|
After Width: | Height: | Size: 340 KiB |
BIN
assets/uploads/profileImage-1755934599888-605173062.png
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
assets/uploads/profileImage-1755937934434-116283125.jpg
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
assets/uploads/profileImage-1755946669630-126189068.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/uploads/profileImage-1755947001183-889093929.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/uploads/profileImage-1755953728360-115123395.jpg
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
assets/uploads/profileImage-1755956983627-613659928.jpg
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
assets/uploads/profileImage-1755958734546-548952268.jpg
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
assets/uploads/profileImage-1756035516571-888403744.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/uploads/profileImage-1756039374205-906295223.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/uploads/profileImage-1756040589088-221180619.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/uploads/profileImage-1756040607074-717639494.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/uploads/profileImage-1756043249603-388360106.png
Normal file
|
After Width: | Height: | Size: 85 KiB |
BIN
assets/uploads/profileImage-1756043320066-238311781.jpg
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
assets/uploads/profileImage-1756043639121-64840711.png
Normal file
|
After Width: | Height: | Size: 449 KiB |
BIN
assets/uploads/profileImage-1756043684612-599737597.jpg
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
assets/uploads/profileImage-1756043988693-513713031.jpg
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
assets/uploads/profileImage-1756044017376-178693076.jpg
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
assets/uploads/profileImage-1756044044280-781994271.jpg
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
assets/uploads/profileImage-1756044615444-224911673.png
Normal file
|
After Width: | Height: | Size: 120 KiB |
@@ -3,6 +3,13 @@
|
||||
"collection": "@nestjs/schematics",
|
||||
"sourceRoot": "src",
|
||||
"compilerOptions": {
|
||||
"deleteOutDir": true
|
||||
"deleteOutDir": true,
|
||||
"assets": [
|
||||
{
|
||||
"include": "../assets/**",
|
||||
"watchAssets": true,
|
||||
"outDir": "dist/assets"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
338
package-lock.json
generated
@@ -11,11 +11,14 @@
|
||||
"dependencies": {
|
||||
"@nestjs/common": "^11.0.1",
|
||||
"@nestjs/core": "^11.0.1",
|
||||
"@nestjs/platform-express": "^11.0.1",
|
||||
"@nestjs/platform-express": "^11.1.6",
|
||||
"@nestjs/platform-socket.io": "^11.1.6",
|
||||
"@nestjs/serve-static": "^5.0.3",
|
||||
"@nestjs/swagger": "^11.2.0",
|
||||
"@nestjs/websockets": "^11.1.6",
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.14.2",
|
||||
"multer": "^2.0.2",
|
||||
"prisma": "^6.14.0",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"rxjs": "^7.8.1"
|
||||
@@ -29,6 +32,7 @@
|
||||
"@prisma/client": "^6.14.0",
|
||||
"@types/express": "^5.0.0",
|
||||
"@types/jest": "^30.0.0",
|
||||
"@types/multer": "^2.0.0",
|
||||
"@types/node": "^22.10.7",
|
||||
"@types/supertest": "^6.0.2",
|
||||
"eslint": "^9.18.0",
|
||||
@@ -2425,6 +2429,25 @@
|
||||
"@nestjs/core": "^11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nestjs/platform-socket.io": {
|
||||
"version": "11.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-11.1.6.tgz",
|
||||
"integrity": "sha512-ozm+OKiRiFLNQdFLA3ULDuazgdVaPrdRdgtG/+404T7tcROXpbUuFL0eEmWJpG64CxMkBNwamclUSH6J0AeU7A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"socket.io": "4.8.1",
|
||||
"tslib": "2.8.1"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/nest"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@nestjs/common": "^11.0.0",
|
||||
"@nestjs/websockets": "^11.0.0",
|
||||
"rxjs": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nestjs/schematics": {
|
||||
"version": "11.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-11.0.7.tgz",
|
||||
@@ -2530,6 +2553,29 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@nestjs/websockets": {
|
||||
"version": "11.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-11.1.6.tgz",
|
||||
"integrity": "sha512-jlBX5QpqhfEVfxkwxTesIjgl0bdhgFMoORQYzjRg1i+Z+Qouf4KmjNPv5DZE3DZRDg91E+3Bpn0VgW0Yfl94ng==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"iterare": "1.2.1",
|
||||
"object-hash": "3.0.0",
|
||||
"tslib": "2.8.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@nestjs/common": "^11.0.0",
|
||||
"@nestjs/core": "^11.0.0",
|
||||
"@nestjs/platform-socket.io": "^11.0.0",
|
||||
"reflect-metadata": "^0.1.12 || ^0.2.0",
|
||||
"rxjs": "^7.1.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@nestjs/platform-socket.io": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@noble/hashes": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
|
||||
@@ -2745,6 +2791,12 @@
|
||||
"@sinonjs/commons": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@socket.io/component-emitter": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz",
|
||||
"integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@standard-schema/spec": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz",
|
||||
@@ -2887,6 +2939,15 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"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==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/eslint": {
|
||||
"version": "9.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz",
|
||||
@@ -3007,11 +3068,20 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/multer": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/multer/-/multer-2.0.0.tgz",
|
||||
"integrity": "sha512-C3Z9v9Evij2yST3RSBktxP9STm6OdMc5uR1xF1SGr98uv8dUlAL2hqwrZ3GVB3uyMyiegnscEK6PGtYvNrjTjw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/express": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.17.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.17.2.tgz",
|
||||
"integrity": "sha512-gL6z5N9Jm9mhY+U2KXZpteb+09zyffliRkZyZOHODGATyC5B1Jt/7TzuuiLkFsSUMLbS1OLmlj/E+/3KF4Q/4w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.21.0"
|
||||
@@ -4206,6 +4276,15 @@
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/base64id": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
|
||||
"integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^4.5.0 || >= 5.9"
|
||||
}
|
||||
},
|
||||
"node_modules/bl": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||
@@ -5167,6 +5246,95 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/engine.io": {
|
||||
"version": "6.6.4",
|
||||
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.4.tgz",
|
||||
"integrity": "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/cors": "^2.8.12",
|
||||
"@types/node": ">=10.0.0",
|
||||
"accepts": "~1.3.4",
|
||||
"base64id": "2.0.0",
|
||||
"cookie": "~0.7.2",
|
||||
"cors": "~2.8.5",
|
||||
"debug": "~4.3.1",
|
||||
"engine.io-parser": "~5.2.1",
|
||||
"ws": "~8.17.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/engine.io-parser": {
|
||||
"version": "5.2.3",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz",
|
||||
"integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/engine.io/node_modules/accepts": {
|
||||
"version": "1.3.8",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
||||
"integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-types": "~2.1.34",
|
||||
"negotiator": "0.6.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/engine.io/node_modules/debug": {
|
||||
"version": "4.3.7",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
|
||||
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/engine.io/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/engine.io/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/engine.io/node_modules/negotiator": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
|
||||
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/enhanced-resolve": {
|
||||
"version": "5.18.3",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
|
||||
@@ -8132,6 +8300,15 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/object-hash": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
|
||||
"integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/object-inspect": {
|
||||
"version": "1.13.4",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
|
||||
@@ -9175,6 +9352,141 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io": {
|
||||
"version": "4.8.1",
|
||||
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz",
|
||||
"integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"accepts": "~1.3.4",
|
||||
"base64id": "~2.0.0",
|
||||
"cors": "~2.8.5",
|
||||
"debug": "~4.3.2",
|
||||
"engine.io": "~6.6.0",
|
||||
"socket.io-adapter": "~2.5.2",
|
||||
"socket.io-parser": "~4.2.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io-adapter": {
|
||||
"version": "2.5.5",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz",
|
||||
"integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "~4.3.4",
|
||||
"ws": "~8.17.1"
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io-adapter/node_modules/debug": {
|
||||
"version": "4.3.7",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
|
||||
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io-parser": {
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
|
||||
"integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
"debug": "~4.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io-parser/node_modules/debug": {
|
||||
"version": "4.3.7",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
|
||||
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io/node_modules/accepts": {
|
||||
"version": "1.3.8",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
||||
"integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-types": "~2.1.34",
|
||||
"negotiator": "0.6.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io/node_modules/debug": {
|
||||
"version": "4.3.7",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
|
||||
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io/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/socket.io/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/socket.io/node_modules/negotiator": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
|
||||
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.7.4",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
|
||||
@@ -10152,7 +10464,6 @@
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
||||
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/universalify": {
|
||||
@@ -10664,6 +10975,27 @@
|
||||
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
|
||||
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": ">=5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/xtend": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||
|
||||
@@ -22,11 +22,14 @@
|
||||
"dependencies": {
|
||||
"@nestjs/common": "^11.0.1",
|
||||
"@nestjs/core": "^11.0.1",
|
||||
"@nestjs/platform-express": "^11.0.1",
|
||||
"@nestjs/platform-express": "^11.1.6",
|
||||
"@nestjs/platform-socket.io": "^11.1.6",
|
||||
"@nestjs/serve-static": "^5.0.3",
|
||||
"@nestjs/swagger": "^11.2.0",
|
||||
"@nestjs/websockets": "^11.1.6",
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.14.2",
|
||||
"multer": "^2.0.2",
|
||||
"prisma": "^6.14.0",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"rxjs": "^7.8.1"
|
||||
@@ -40,6 +43,7 @@
|
||||
"@prisma/client": "^6.14.0",
|
||||
"@types/express": "^5.0.0",
|
||||
"@types/jest": "^30.0.0",
|
||||
"@types/multer": "^2.0.0",
|
||||
"@types/node": "^22.10.7",
|
||||
"@types/supertest": "^6.0.2",
|
||||
"eslint": "^9.18.0",
|
||||
|
||||
12
prisma/migrations/20250819161859_/migration.sql
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `text` on the `Candidate` table. All the data in the column will be lost.
|
||||
- Added the required column `justification` to the `Candidate` table without a default value. This is not possible if the table is not empty.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "public"."Candidate" DROP COLUMN "text",
|
||||
ADD COLUMN "justification" TEXT NOT NULL,
|
||||
ALTER COLUMN "hobbies" DROP NOT NULL,
|
||||
ALTER COLUMN "image" DROP NOT NULL;
|
||||
9
prisma/migrations/20250822104249_init/migration.sql
Normal file
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `image` on the `Candidate` table. All the data in the column will be lost.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "public"."Candidate" DROP COLUMN "image",
|
||||
ADD COLUMN "profileImage" TEXT;
|
||||
@@ -15,14 +15,14 @@ datasource db {
|
||||
}
|
||||
|
||||
model Candidate {
|
||||
id Int @id @default(autoincrement())
|
||||
fullName String
|
||||
email String
|
||||
phoneNumber String
|
||||
age Int
|
||||
cityOrRegion String
|
||||
hobbies String
|
||||
text String
|
||||
image String
|
||||
createdAt DateTime @default(now())
|
||||
id Int @id @default(autoincrement())
|
||||
fullName String
|
||||
email String
|
||||
phoneNumber String
|
||||
age Int
|
||||
cityOrRegion String
|
||||
hobbies String?
|
||||
justification String
|
||||
profileImage String?
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
import { BadRequestException, Body, Controller, Get, NotFoundException, Param, ParseIntPipe, Post, Put } from '@nestjs/common';
|
||||
import { BadRequestException, Body, Controller, Get, NotFoundException, Param, ParseIntPipe, Post, Put, UploadedFile, UseInterceptors } from '@nestjs/common';
|
||||
import { RegisterDto } from './dto/register.dto';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { PrismaService } from './services/prisma.service';
|
||||
import { FileInterceptor } from '@nestjs/platform-express';
|
||||
import { diskStorage } from 'multer';
|
||||
import { extname } from 'path';
|
||||
import { AppGetaway } from './app.getaway';
|
||||
|
||||
@ApiTags('App')
|
||||
@Controller('app')
|
||||
export class AppController {
|
||||
constructor(private prisma: PrismaService) { }
|
||||
constructor(private prisma: PrismaService, private socketService: AppGetaway) { }
|
||||
|
||||
|
||||
@Get('candidates')
|
||||
getCandidateList() {
|
||||
@@ -14,30 +19,80 @@ export class AppController {
|
||||
select: {
|
||||
id: true,
|
||||
fullName: true,
|
||||
image: true,
|
||||
age: true,
|
||||
cityOrRegion: true,
|
||||
profileImage: true,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@Get('candidate/:id')
|
||||
getCandidateDetails(@Param('id', ParseIntPipe) id: number) {
|
||||
return this.prisma.candidate.findFirst({where: {id : id}});
|
||||
return this.prisma.candidate.findFirst({ where: { id: id } });
|
||||
}
|
||||
|
||||
@Post('register')
|
||||
register(@Body() dto: RegisterDto) {
|
||||
return this.prisma.candidate.create({ data: { ...dto, createdAt: new Date() } });
|
||||
@UseInterceptors(FileInterceptor('profileImage', {
|
||||
storage: diskStorage({
|
||||
destination: 'assets/uploads',
|
||||
filename: (req, file, cb) => {
|
||||
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);
|
||||
const ext = extname(file.originalname);
|
||||
cb(null, `${file.fieldname}-${uniqueSuffix}${ext}`);
|
||||
}
|
||||
})
|
||||
}))
|
||||
async register(
|
||||
@UploadedFile() file: Express.Multer.File,
|
||||
@Body() dto: RegisterDto
|
||||
) {
|
||||
const imagePath = file ? file.filename : null;
|
||||
const savedCandidate = await this.prisma.candidate.create({
|
||||
data: {
|
||||
...dto,
|
||||
profileImage: imagePath,
|
||||
createdAt: new Date(),
|
||||
},
|
||||
});
|
||||
this.socketService.onAddCandidate(savedCandidate);
|
||||
|
||||
return savedCandidate;
|
||||
}
|
||||
|
||||
@Put('candidate/:id')
|
||||
async update(@Param('id', ParseIntPipe) id: number, @Body() dto: RegisterDto) {
|
||||
const candidate = await this.prisma.candidate.findFirst({ where: { id: id } });
|
||||
if (!candidate) throw new NotFoundException(`candidate with id ${id} not found`);
|
||||
@UseInterceptors(FileInterceptor('profileImage', {
|
||||
storage: diskStorage({
|
||||
destination: 'assets/uploads',
|
||||
filename: (req, file, cb) => {
|
||||
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);
|
||||
const ext = extname(file.originalname);
|
||||
cb(null, `${file.fieldname}-${uniqueSuffix}${ext}`);
|
||||
}
|
||||
})
|
||||
}))
|
||||
async update(
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@UploadedFile() file: Express.Multer.File,
|
||||
@Body() dto: RegisterDto
|
||||
) {
|
||||
const candidate = await this.prisma.candidate.findFirst({ where: { id } });
|
||||
if (!candidate) throw new NotFoundException(`Candidate with id ${id} not found`);
|
||||
|
||||
const dayMilliseconds = 86400000;
|
||||
const expirationDate = new Date(candidate.createdAt.valueOf() + 3 * dayMilliseconds);
|
||||
if (expirationDate < new Date()) throw new BadRequestException(`can not edit candidate form after 3 days`);
|
||||
await this.prisma.candidate.update({ where: { id: id }, data: { id, ...dto } });
|
||||
if (expirationDate < new Date()) throw new BadRequestException(`Cannot edit candidate form after 3 days`);
|
||||
|
||||
const profileImagePath = file ? file.filename : candidate.profileImage;
|
||||
|
||||
const updatedCandidate = await this.prisma.candidate.update({
|
||||
where: { id },
|
||||
data: {
|
||||
...dto,
|
||||
profileImage: profileImagePath,
|
||||
},
|
||||
});
|
||||
this.socketService.onUpdateCandidate(updatedCandidate);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
26
src/app.getaway.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { MessageBody, OnGatewayConnection, OnGatewayDisconnect, SubscribeMessage, WebSocketGateway, WebSocketServer } from "@nestjs/websockets";
|
||||
import { Server, Socket } from "socket.io";
|
||||
|
||||
@WebSocketGateway({
|
||||
cors: true
|
||||
})
|
||||
|
||||
export class AppGetaway implements OnGatewayDisconnect, OnGatewayConnection {
|
||||
@WebSocketServer() server: Server
|
||||
|
||||
handleDisconnect(client: Socket) {
|
||||
console.log(`${client.id} disconnected`)
|
||||
}
|
||||
|
||||
handleConnection(client: Socket, ...args: any[]) {
|
||||
console.log(`${client.id} connected`)
|
||||
}
|
||||
|
||||
onAddCandidate(registrationData: any) {
|
||||
this.server.emit('candidateRegistered', registrationData);
|
||||
}
|
||||
|
||||
onUpdateCandidate(updatedData: any) {
|
||||
this.server.emit('candidateUpdated', updatedData);
|
||||
}
|
||||
}
|
||||
@@ -3,14 +3,21 @@ import { AppController } from './app.controller';
|
||||
import { ServeStaticModule } from '@nestjs/serve-static';
|
||||
import { join } from 'path';
|
||||
import { PrismaService } from './services/prisma.service';
|
||||
import { AppGetaway } from './app.getaway';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ServeStaticModule.forRoot({
|
||||
rootPath: join(__dirname, 'client'),
|
||||
}),
|
||||
ServeStaticModule.forRoot(
|
||||
{
|
||||
rootPath: join(__dirname, 'assets/client'),
|
||||
renderPath: '/'
|
||||
},
|
||||
{
|
||||
rootPath: join(__dirname, 'assets/uploads'),
|
||||
serveRoot: '/uploads',
|
||||
}),
|
||||
],
|
||||
controllers: [AppController],
|
||||
providers: [PrismaService],
|
||||
providers: [PrismaService, AppGetaway],
|
||||
})
|
||||
export class AppModule { }
|
||||
|
||||
@@ -1,22 +1,27 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsInt } from 'class-validator';
|
||||
import { IsInt, IsOptional, IsString } from 'class-validator';
|
||||
|
||||
export class RegisterDto {
|
||||
@ApiProperty({ required: true })
|
||||
@IsString()
|
||||
fullName: string;
|
||||
@ApiProperty({ required: true })
|
||||
@IsString()
|
||||
email: string;
|
||||
@ApiProperty({ required: true })
|
||||
@IsString()
|
||||
phoneNumber: string;
|
||||
@ApiProperty({ required: true })
|
||||
@IsInt()
|
||||
age: number;
|
||||
@ApiProperty({ required: true })
|
||||
@IsString()
|
||||
cityOrRegion: string;
|
||||
@ApiProperty({ required: false })
|
||||
hobbies: string;
|
||||
@ApiProperty({ required: false })
|
||||
text: string;
|
||||
@ApiProperty({ required: false })
|
||||
image: string;
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
hobbies?: string;
|
||||
@ApiProperty({ required: true })
|
||||
@IsString()
|
||||
justification: string;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ async function bootstrap() {
|
||||
);
|
||||
setupSwagger(app);
|
||||
app.enableCors({
|
||||
origin: true,
|
||||
origin: [true],
|
||||
methods: [
|
||||
'GET',
|
||||
'HEAD',
|
||||
|
||||
@@ -20,6 +20,6 @@
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noImplicitAny": true,
|
||||
"strictBindCallApply": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
}
|
||||
}
|
||||