diff --git a/.babelrc b/.babelrc index 1320b9a..8aa924d 100644 --- a/.babelrc +++ b/.babelrc @@ -1,3 +1,3 @@ { "presets": ["@babel/preset-env"] -} +} \ No newline at end of file diff --git a/data/seed.js b/data/seed.js new file mode 100644 index 0000000..cf5be0f --- /dev/null +++ b/data/seed.js @@ -0,0 +1,25 @@ +import mongoose from 'mongoose' +import dotenv from 'dotenv' +import Thought from '../models/Thought.js' +import thoughts from './thoughts.json' + +dotenv.config() + +const mongoUrl = process.env.MONGO_URL || 'mongodb://127.0.0.1:27017/happythoughts' + +mongoose + .connect(mongoUrl) + .then(async () => { + console.log('✅ Connected to MongoDB for seeding') + // 1. Clear existing documents + await Thought.deleteMany() + // 2. Insert our dummy data + const inserted = await Thought.insertMany(thoughts) + console.log(`🌱 Seeded ${inserted.length} thoughts`) + }) + .catch((err) => { + console.error('❌ Seeding error:', err) + }) + .finally(() => { + mongoose.connection.close() + }) \ No newline at end of file diff --git a/data.json b/data/thoughts.json similarity index 94% rename from data.json rename to data/thoughts.json index a2c844f..1124d7f 100644 --- a/data.json +++ b/data/thoughts.json @@ -110,12 +110,5 @@ "hearts": 3, "createdAt": "2025-05-20T03:57:40.322Z", "__v": 0 - }, - { - "_id": "682bab8c12155b00101732ce", - "message": "Berlin baby", - "hearts": 37, - "createdAt": "2025-05-19T22:07:08.999Z", - "__v": 0 } ] \ No newline at end of file diff --git a/models/Thought.js b/models/Thought.js new file mode 100644 index 0000000..ec2bd8f --- /dev/null +++ b/models/Thought.js @@ -0,0 +1,22 @@ +import mongoose from 'mongoose' + +const { Schema, model } = mongoose + +const ThoughtSchema = new Schema({ + message: { + type: String, + required: true, + minlength: 5, + maxlength: 140 + }, + hearts: { + type: Number, + default: 0 + }, + createdAt: { + type: Date, + default: () => new Date() + } +}) + +export default model('Thought', ThoughtSchema) \ No newline at end of file diff --git a/package.json b/package.json index bf25bb6..11eb5ee 100644 --- a/package.json +++ b/package.json @@ -4,16 +4,22 @@ "description": "Project API", "scripts": { "start": "babel-node server.js", - "dev": "nodemon server.js --exec babel-node" + "dev": "nodemon server.js --exec babel-node", + "seed": "babel-node data/seed.js" }, "author": "", "license": "ISC", "dependencies": { - "@babel/core": "^7.17.9", - "@babel/node": "^7.16.8", - "@babel/preset-env": "^7.16.11", "cors": "^2.8.5", + "dotenv": "^16.5.0", "express": "^4.17.3", - "nodemon": "^3.0.1" + "express-list-endpoints": "^7.1.1", + "mongoose": "^8.15.1" + }, + "devDependencies": { + "@babel/core": "^7.27.4", + "@babel/node": "^7.27.1", + "@babel/preset-env": "^7.27.2", + "nodemon": "^3.1.10" } } diff --git a/server.js b/server.js index f47771b..0f35879 100644 --- a/server.js +++ b/server.js @@ -1,22 +1,113 @@ -import cors from "cors" -import express from "express" +import express from 'express' +import cors from 'cors' +import listEndpoints from 'express-list-endpoints' +import dotenv from 'dotenv' +import mongoose from 'mongoose' +import Thought from './models/Thought.js' + +dotenv.config() -// Defines the port the app will run on. Defaults to 8080, but can be overridden -// when starting the server. Example command to overwrite PORT env variable value: -// PORT=9000 npm start -const port = process.env.PORT || 8080 const app = express() +const PORT = process.env.PORT || 8080 + +// Connect to MongoDB +const mongoUrl = process.env.MONGO_URL || 'mongodb://127.0.0.1:27017/happythoughts' +mongoose + .connect(mongoUrl) + .then(() => console.log('✅ Connected to MongoDB')) + .catch((err) => console.error('❌ MongoDB connection error:', err)) -// Add middlewares to enable cors and json body parsing +// Middleware app.use(cors()) app.use(express.json()) -// Start defining your routes here -app.get("/", (req, res) => { - res.send("Hello Technigo!") +// 1) API documentation & welcome message +app.get('/', (req, res) => { + res.json({ + message: 'Welcome to the Happy Thoughts API', + endpoints: listEndpoints(app) + }) }) -// Start the server -app.listen(port, () => { - console.log(`Server running on http://localhost:${port}`) +// 2) Collection endpoint: get all thoughts, optional filter by hearts +app.get('/thoughts', async (req, res, next) => { + try { + const { hearts } = req.query + const filter = hearts ? { hearts: Number(hearts) } : {} + const thoughts = await Thought.find(filter).sort({ createdAt: -1 }) + res.status(200).json(thoughts) + } catch (err) { + next(err) + } +}) + +// 3) Single‐item endpoint: get one thought by ID +app.get('/thoughts/:id', async (req, res, next) => { + try { + const thought = await Thought.findById(req.params.id) + if (!thought) { + return res + .status(404) + .json({ error: `Thought with ID '${req.params.id}' not found` }) + } + res.status(200).json(thought) + } catch (err) { + next(err) + } +}) + +// 4) Create a new thought +app.post('/thoughts', async (req, res, next) => { + try { + const { message } = req.body + const newThought = new Thought({ message }) + const savedThought = await newThought.save() + res.status(201).json(savedThought) + } catch (err) { + next(err) + } }) + +// 5) Update a thought (edit message or hearts) +app.put('/thoughts/:id', async (req, res, next) => { + try { + const updated = await Thought.findByIdAndUpdate( + req.params.id, + req.body, + { new: true, runValidators: true } + ) + if (!updated) { + return res + .status(404) + .json({ error: `Thought with ID '${req.params.id}' not found` }) + } + res.json(updated) + } catch (err) { + next(err) + } +}) + +// 6) Delete a thought +app.delete('/thoughts/:id', async (req, res, next) => { + try { + const deleted = await Thought.findByIdAndDelete(req.params.id) + if (!deleted) { + return res + .status(404) + .json({ error: `Thought with ID '${req.params.id}' not found` }) + } + res.json({ success: true, deletedId: req.params.id }) + } catch (err) { + next(err) + } +}) + +// Error handler +app.use((err, req, res, next) => { + res.status(400).json({ error: err.message }) +}) + +// Start the server +app.listen(PORT, () => { + console.log(`Server running on http://localhost:${PORT}`) +}) \ No newline at end of file