From bd8a7f86a3554db80fef53e98d9a01b66d7296c9 Mon Sep 17 00:00:00 2001 From: Maira Tariq Date: Mon, 15 Dec 2025 13:38:29 +0000 Subject: [PATCH] feat: configure upload-cv endpoint - Configure CORS to explicitly allow requests from the frontend client.- Implement in the main router: - Add middleware to handle file uploads (key: 'cv'). - Add logic to parse stringified array from . - Integrate middleware to process PDF/DOCX files.- Ensure correct error handling for file parsing and empty uploads. --- .vscode/settings.json | 4 ++++ package-lock.json | 8 -------- routes/index.ts | 34 +++++++++++++++++++++++++++++++--- server.ts | 1 + 4 files changed, 36 insertions(+), 11 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..f82fc39 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index e5b0a23..e2fd3b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1427,7 +1427,6 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -1535,7 +1534,6 @@ "integrity": "sha512-jCzKdm/QK0Kg4V4IK/oMlRZlY+QOcdjv89U2NgKHZk1CYTj82/RVSx1mV/0gqCVMJ/DA+Zf/S4NBWNF8GQ+eqQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.48.0", "@typescript-eslint/types": "8.48.0", @@ -1886,7 +1884,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2554,7 +2551,6 @@ "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -4469,7 +4465,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -4621,7 +4616,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -4720,7 +4714,6 @@ "integrity": "sha512-tI2l/nFHC5rLh7+5+o7QjKjSR04ivXDF4jcgV0f/bTQ+OJiITy5S6gaynVsEM+7RqzufMnVbIon6Sr5x1SDYaQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", @@ -4814,7 +4807,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, diff --git a/routes/index.ts b/routes/index.ts index 552ebb3..0eb3dd6 100644 --- a/routes/index.ts +++ b/routes/index.ts @@ -20,16 +20,44 @@ const upload = multer({ storage: multer.memoryStorage() }); // keep file in memo // this endpoint is intentionally put here to avoid auth // it will be moved to users_CVsRoutes after more integration testing ROUTER.post('/upload-cv', upload.single('cv'), async (req, res) => { + // Validation: Check if file exists if (!req.file) { return res.status(400).json({ error: 'No file uploaded' }); } + // Extract Dealbreakers + // Multer populates req.body with text fields. + // Since we JSON.stringify'd the array on frontend, we must JSON.parse it here. + let dealbreakers: string[] = []; + if (req.body.dealbreakers) { + try { + dealbreakers = JSON.parse(req.body.dealbreakers); + } catch (e) { + console.warn('Failed to parse dealbreakers JSON', e); + // Fallback: treat it as empty or single string if needed + } + } + // Extract Text from CV (using middleware) try { - const text = await extractCvText(req.file); - res.json({ text }); + const cvText = await extractCvText(req.file); + console.log('Extracted CV Length:', cvText.length); + console.log('Received Dealbreakers:', dealbreakers); + // // TO DO? Return combined data (or save to DB) + // res.json({ + // message: 'Bio received successfully', + // data: { + // cvText: cvText, + // dealbreakers: dealbreakers, + // }, + // }); + + res.json({ cvText }); } catch (err) { console.error(err); - res.status(500).json({ error: 'Failed to parse CV' }); + // Better error handling for the client + const errorMessage = + err instanceof Error ? err.message : 'Failed to parse CV'; + res.status(500).json({ error: errorMessage }); } }); diff --git a/server.ts b/server.ts index 3045fc0..6b554b0 100644 --- a/server.ts +++ b/server.ts @@ -5,6 +5,7 @@ import cors from 'cors'; const app = express(); +// CORS configuration - allow requests from frontend server app.use( cors({ origin: 'http://localhost:5173',