Skip to content

Commit da752eb

Browse files
committed
refactor: update package.json and server.js for Lemoncode frontend
- Renamed project to "lemoncode-frontend" and updated description. - Changed main entry point to "server.js". - Updated Node.js engine compatibility to include versions 18.x and 20.x. - Added start and dev scripts for running the server. - Added Jest as a testing framework and created test scripts. - Updated dependencies: ejs to version 3.1.10 and express to version 4.19.2. - Removed dynamic import for node-fetch in server.js.
1 parent d17cf6d commit da752eb

File tree

24 files changed

+4423
-2054
lines changed

24 files changed

+4423
-2054
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,4 @@ msbuild.wrn
6262
01-contenedores/lemoncode-challenge/dotnet-stack/backend/obj/Debug/netcoreapp3.1/backend.AssemblyInfo.cs
6363
01-contenedores/lemoncode-challenge/dotnet-stack/backend/obj/Debug/netcoreapp3.1/backend.GeneratedMSBuildEditorConfig.editorconfig
6464
01-contenedores/lemoncode-challenge/dotnet-stack/backend/obj/Debug/netcoreapp3.1/backend.AssemblyInfo.cs
65+
01-contenedores/lemoncode-challenge/node-stack/backend/CHALLENGE.md
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
require('dotenv').config();
2+
3+
const express = require('express');
4+
const cors = require('cors');
5+
const { MongoClient, ObjectId } = require('mongodb');
6+
7+
const app = express();
8+
9+
// ============================================
10+
// CONFIGURACIÓN
11+
// ============================================
12+
const DB_URL = process.env.DATABASE_URL || 'mongodb://localhost:27017';
13+
const DB_NAME = process.env.DATABASE_NAME || 'TopicstoreDb';
14+
const HOST = process.env.HOST || '0.0.0.0';
15+
const PORT = 5001;
16+
17+
let db;
18+
let topicsCollection;
19+
let mongoClient;
20+
21+
// ============================================
22+
// MIDDLEWARES
23+
// ============================================
24+
app.use(cors());
25+
app.use(express.json());
26+
app.use(express.urlencoded({ extended: true }));
27+
28+
// ============================================
29+
// CONEXIÓN A MONGODB
30+
// ============================================
31+
async function connectDB() {
32+
try {
33+
console.log('🔄 Conectando a MongoDB...');
34+
mongoClient = new MongoClient(DB_URL);
35+
await mongoClient.connect();
36+
console.log('✅ Conexión a MongoDB exitosa');
37+
38+
db = mongoClient.db(DB_NAME);
39+
topicsCollection = db.collection('Topics');
40+
console.log('📋 Colección Topics cargada');
41+
} catch (error) {
42+
console.error('❌ Error al conectar a MongoDB:', error.message);
43+
process.exit(1);
44+
}
45+
}
46+
47+
// ============================================
48+
// RUTAS - TOPICS
49+
// ============================================
50+
51+
// GET /api/topics - Obtener todos los tópicos
52+
app.get('/api/topics', async (req, res) => {
53+
try {
54+
console.log('📥 GET /api/topics');
55+
const topics = await topicsCollection.find({}).toArray();
56+
console.log(`✅ Se obtuvieron ${topics.length} tópicos`);
57+
res.json(topics);
58+
} catch (error) {
59+
console.error('❌ Error al obtener tópicos:', error.message);
60+
res.status(500).json({ error: 'Error al obtener tópicos' });
61+
}
62+
});
63+
64+
// GET /api/topics/:id - Obtener un tópico por ID
65+
app.get('/api/topics/:id', async (req, res) => {
66+
try {
67+
const { id } = req.params;
68+
console.log(`📥 GET /api/topics/${id}`);
69+
70+
if (!ObjectId.isValid(id)) {
71+
return res.status(400).json({ error: 'ID inválido' });
72+
}
73+
74+
const topic = await topicsCollection.findOne({ _id: new ObjectId(id) });
75+
if (!topic) {
76+
return res.status(404).json({ error: 'Tópico no encontrado' });
77+
}
78+
79+
console.log(`✅ Tópico ${id} obtenido`);
80+
res.json(topic);
81+
} catch (error) {
82+
console.error('❌ Error al obtener tópico:', error.message);
83+
res.status(500).json({ error: 'Error al obtener tópico' });
84+
}
85+
});
86+
87+
// POST /api/topics - Crear un nuevo tópico
88+
app.post('/api/topics', async (req, res) => {
89+
try {
90+
const topic = req.body;
91+
console.log(`📥 POST /api/topics - ${JSON.stringify(topic)}`);
92+
93+
if (!topic.Name) {
94+
return res.status(400).json({ error: 'El campo Name es requerido' });
95+
}
96+
97+
const result = await topicsCollection.insertOne(topic);
98+
const createdTopic = { _id: result.insertedId, ...topic };
99+
console.log(`✅ Tópico creado: ${topic.Name}`);
100+
res.status(201).json(createdTopic);
101+
} catch (error) {
102+
console.error('❌ Error al crear tópico:', error.message);
103+
res.status(500).json({ error: 'Error al crear tópico' });
104+
}
105+
});
106+
107+
// PUT /api/topics/:id - Actualizar un tópico
108+
app.put('/api/topics/:id', async (req, res) => {
109+
try {
110+
const { id } = req.params;
111+
const topic = req.body;
112+
console.log(`📥 PUT /api/topics/${id} - ${JSON.stringify(topic)}`);
113+
114+
if (!ObjectId.isValid(id)) {
115+
return res.status(400).json({ error: 'ID inválido' });
116+
}
117+
118+
const result = await topicsCollection.updateOne(
119+
{ _id: new ObjectId(id) },
120+
{ $set: topic }
121+
);
122+
123+
if (result.matchedCount === 0) {
124+
return res.status(404).json({ error: 'Tópico no encontrado' });
125+
}
126+
127+
console.log(`✅ Tópico ${id} actualizado`);
128+
res.json({ _id: id, ...topic });
129+
} catch (error) {
130+
console.error('❌ Error al actualizar tópico:', error.message);
131+
res.status(500).json({ error: 'Error al actualizar tópico' });
132+
}
133+
});
134+
135+
// DELETE /api/topics/:id - Eliminar un tópico
136+
app.delete('/api/topics/:id', async (req, res) => {
137+
try {
138+
const { id } = req.params;
139+
console.log(`📥 DELETE /api/topics/${id}`);
140+
141+
if (!ObjectId.isValid(id)) {
142+
return res.status(400).json({ error: 'ID inválido' });
143+
}
144+
145+
const result = await topicsCollection.deleteOne({ _id: new ObjectId(id) });
146+
147+
if (result.deletedCount === 0) {
148+
return res.status(404).json({ error: 'Tópico no encontrado' });
149+
}
150+
151+
console.log(`✅ Tópico ${id} eliminado`);
152+
res.status(204).send();
153+
} catch (error) {
154+
console.error('❌ Error al eliminar tópico:', error.message);
155+
res.status(500).json({ error: 'Error al eliminar tópico' });
156+
}
157+
});
158+
159+
// ============================================
160+
// INICIAR SERVIDOR
161+
// ============================================
162+
async function startServer() {
163+
try {
164+
console.log('\n🔧 Inicializando backend...');
165+
await connectDB();
166+
167+
app.listen(PORT, HOST, () => {
168+
const url = `http://${HOST === '0.0.0.0' ? 'localhost' : HOST}:${PORT}`;
169+
console.log('');
170+
console.log('═══════════════════════════════════════════════════════════════');
171+
console.log(`🚀 Servidor ejecutándose en: ${url}/api/topics`);
172+
console.log('═══════════════════════════════════════════════════════════════');
173+
console.log('');
174+
});
175+
} catch (error) {
176+
console.error('❌ Error al iniciar servidor:', error.message);
177+
process.exit(1);
178+
}
179+
}
180+
181+
// Iniciar la aplicación
182+
startServer();
183+
184+
// Manejo de cierre graceful
185+
process.on('SIGTERM', async () => {
186+
console.log('\n🛑 Recibido SIGTERM, cerrando gracefully...');
187+
if (mongoClient) {
188+
await mongoClient.close();
189+
console.log('✅ Conexión a MongoDB cerrada');
190+
}
191+
process.exit(0);
192+
});
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
@baseUrl = http://localhost:5001/api
2+
@contentType = application/json
3+
4+
###
5+
# ============================================
6+
# GET - Obtener todos los tópicos
7+
# ============================================
8+
GET {{baseUrl}}/topics
9+
10+
###
11+
# ============================================
12+
# POST - Crear un nuevo tópico
13+
# ============================================
14+
POST {{baseUrl}}/topics
15+
Content-Type: {{contentType}}
16+
17+
{
18+
"Name": "Docker"
19+
}
20+
21+
###
22+
# ============================================
23+
# POST - Crear otro tópico
24+
# ============================================
25+
POST {{baseUrl}}/topics
26+
Content-Type: {{contentType}}
27+
28+
{
29+
"Name": "Kubernetes"
30+
}
31+
32+
###
33+
# ============================================
34+
# POST - Crear otro tópico
35+
# ============================================
36+
POST {{baseUrl}}/topics
37+
Content-Type: {{contentType}}
38+
39+
{
40+
"Name": "DevOps"
41+
}
42+
43+
###
44+
# ============================================
45+
# GET - Obtener un tópico específico (sustituir ID)
46+
# Nota: Copia el _id de una respuesta anterior
47+
# ============================================
48+
GET {{baseUrl}}/topics/PASTE_ID_HERE
49+
50+
###
51+
# ============================================
52+
# PUT - Actualizar un tópico (sustituir ID)
53+
# Nota: Copia el _id de una respuesta anterior
54+
# ============================================
55+
PUT {{baseUrl}}/topics/PASTE_ID_HERE
56+
Content-Type: {{contentType}}
57+
58+
{
59+
"Name": "Docker Updated"
60+
}
61+
62+
###
63+
# ============================================
64+
# DELETE - Eliminar un tópico (sustituir ID)
65+
# Nota: Copia el _id de una respuesta anterior
66+
# ============================================
67+
DELETE {{baseUrl}}/topics/PASTE_ID_HERE

0 commit comments

Comments
 (0)