@@ -2,18 +2,57 @@ import cors from "cors";
22import express from "express" ;
33import { existsSync , mkdirSync , readdirSync , readFileSync , statSync , writeFileSync } from "fs" ;
44import path from "path" ;
5+ import { fileURLToPath } from "url" ;
56import XLSX from "xlsx" ;
67import { run as runScraper } from "./app.js" ;
78import { getConfig } from "./config.js" ;
89import { searchJobsWithCache } from "./pipeline/searchJobsWithCache.js" ;
910import { sources } from "./sources/index.js" ;
1011
12+ const MODULE_DIR = path . dirname ( fileURLToPath ( import . meta. url ) ) ;
13+
1114const DEFAULT_ALLOWED_ORIGINS = [
1215 "https://painel-vagas-lake.vercel.app" ,
1316 "http://localhost:5173" ,
1417 "http://localhost:5174" ,
1518] ;
1619
20+ function getKeywordsFilePath ( ) {
21+ const configuredPath = process . env . KEYWORDS_FILE_PATH ?. trim ( ) ;
22+ return configuredPath
23+ ? path . resolve ( configuredPath )
24+ : path . resolve ( MODULE_DIR , "db" , "environment.json" ) ;
25+ }
26+
27+ function normalizeKeywords ( keywords ) {
28+ if ( ! Array . isArray ( keywords ) ) {
29+ return null ;
30+ }
31+
32+ return [ ...new Set ( keywords . map ( ( item ) => String ( item ?? "" ) . trim ( ) ) . filter ( Boolean ) ) ] ;
33+ }
34+
35+ function readEnvironmentData ( ) {
36+ const envPath = getKeywordsFilePath ( ) ;
37+
38+ if ( ! existsSync ( envPath ) ) {
39+ return { KEYWORDS : [ ] } ;
40+ }
41+
42+ try {
43+ const data = JSON . parse ( readFileSync ( envPath , "utf-8" ) ) ;
44+ return data && typeof data === "object" ? data : { KEYWORDS : [ ] } ;
45+ } catch {
46+ return { KEYWORDS : [ ] } ;
47+ }
48+ }
49+
50+ function writeEnvironmentData ( data ) {
51+ const envPath = getKeywordsFilePath ( ) ;
52+ mkdirSync ( path . dirname ( envPath ) , { recursive : true } ) ;
53+ writeFileSync ( envPath , JSON . stringify ( data , null , 2 ) , "utf-8" ) ;
54+ }
55+
1756function parseAllowedOrigins ( value ) {
1857 const configuredOrigins = String ( value ?? "" )
1958 . split ( "," )
@@ -258,27 +297,20 @@ export function createJobsApiApp(options = {}) {
258297 */
259298 app . post ( "/api/keywords" , ( req , res ) => {
260299 try {
261- const { keywords } = req . body ;
300+ const normalizedKeywords = normalizeKeywords ( req . body ?. keywords ) ;
262301
263- if ( ! Array . isArray ( keywords ) ) {
302+ if ( normalizedKeywords === null ) {
264303 return res . status ( 400 ) . json ( {
265304 message : "O campo 'keywords' deve ser um array de strings." ,
266305 } ) ;
267306 }
268307
269- const envPath = path . resolve ( process . cwd ( ) , "src" , "db" , "environment.json" ) ;
270- let envData = { KEYWORDS : [ ] } ;
271-
272- if ( existsSync ( envPath ) ) {
273- try {
274- envData = JSON . parse ( readFileSync ( envPath , "utf-8" ) ) ;
275- } catch ( e ) {
276- // Se o arquivo estiver corrompido, reinicia com o objeto padrao
277- }
278- }
308+ const envData = {
309+ ...readEnvironmentData ( ) ,
310+ KEYWORDS : normalizedKeywords ,
311+ } ;
279312
280- envData . KEYWORDS = keywords ;
281- writeFileSync ( envPath , JSON . stringify ( envData , null , 2 ) , "utf-8" ) ;
313+ writeEnvironmentData ( envData ) ;
282314
283315 return res . json ( {
284316 ok : true ,
@@ -303,28 +335,21 @@ export function createJobsApiApp(options = {}) {
303335 * 200:
304336 * description: Lista de keywords
305337 */
306- app . get ( "/api/keywords" , ( req , res ) => {
307- try {
308- const envPath = path . resolve ( process . cwd ( ) , "src" , "db" , "environment.json" ) ;
309-
310- if ( ! existsSync ( envPath ) ) {
311- return res . json ( { keywords : [ ] } ) ;
312- }
313-
314- const fileContent = readFileSync ( envPath , "utf-8" ) ;
315- const envData = JSON . parse ( fileContent ) ;
338+ app . get ( "/api/keywords" , ( _req , res ) => {
339+ try {
340+ const envData = readEnvironmentData ( ) ;
316341
317- return res . json ( {
318- ok : true ,
319- keywords : envData . KEYWORDS || [ ] ,
320- } ) ;
321- } catch ( error ) {
322- return res . status ( 500 ) . json ( {
323- message : "Erro ao buscar keywords." ,
324- error : error ?. message || "Erro desconhecido" ,
325- } ) ;
326- }
327- } ) ;
342+ return res . json ( {
343+ ok : true ,
344+ keywords : normalizeKeywords ( envData . KEYWORDS ) ?? [ ] ,
345+ } ) ;
346+ } catch ( error ) {
347+ return res . status ( 500 ) . json ( {
348+ message : "Erro ao buscar keywords." ,
349+ error : error ?. message || "Erro desconhecido" ,
350+ } ) ;
351+ }
352+ } ) ;
328353
329354 /**
330355 * @swagger
0 commit comments