From 844376bb315add2a46c54feced62a21ee4f55eb9 Mon Sep 17 00:00:00 2001 From: Julia Demianetc Date: Thu, 22 Jan 2026 07:03:13 +0100 Subject: [PATCH 1/9] installed endpoints, created routs for endpoints list, filtering messages by amount of likes or amount equal or more than likes, added find by id --- data.json | 16 +++---- package.json | 4 +- server.js | 124 +++++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 121 insertions(+), 23 deletions(-) diff --git a/data.json b/data.json index a2c844ff..f0ec719c 100644 --- a/data.json +++ b/data.json @@ -1,13 +1,13 @@ [ - { - "_id": "682bab8c12155b00101732ce", + { + "_id": "682bab8c12155b00101732cb", "message": "Berlin baby", "hearts": 37, "createdAt": "2025-05-19T22:07:08.999Z", "__v": 0 }, { - "_id": "682e53cc4fddf50010bbe739", + "_id": "682e53cc4fddf50010bbe739", "message": "My family!", "hearts": 0, "createdAt": "2025-05-22T22:29:32.232Z", @@ -25,7 +25,7 @@ "message": "Newly washed bedlinen, kids that sleeps through the night.. FINGERS CROSSED 🤞🏼\n", "hearts": 6, "createdAt": "2025-05-21T21:42:23.862Z", - "__v": 0 + "__v": 0 }, { "_id": "682e45804fddf50010bbe736", @@ -53,7 +53,7 @@ "message": "A god joke: \nWhy did the scarecrow win an award?\nBecause he was outstanding in his field!", "hearts": 12, "createdAt": "2025-05-20T20:54:51.082Z", - "__v": 0 + "__v": 0 }, { "_id": "682cebbe17487d0010a298b5", @@ -74,7 +74,7 @@ "message": "Summer is coming...", "hearts": 2, "createdAt": "2025-05-20T15:03:22.379Z", - "__v": 0 + "__v": 0 }, { "_id": "682c706c951f7a0017130024", @@ -113,9 +113,9 @@ }, { "_id": "682bab8c12155b00101732ce", - "message": "Berlin baby", + "message": "London baby", "hearts": 37, "createdAt": "2025-05-19T22:07:08.999Z", "__v": 0 } -] \ No newline at end of file +] diff --git a/package.json b/package.json index bf25bb68..3535ba4c 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "Project API", "scripts": { "start": "babel-node server.js", - "dev": "nodemon server.js --exec babel-node" + "dev": "nodemon server.js --exec babel-node", + "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", @@ -14,6 +15,7 @@ "@babel/preset-env": "^7.16.11", "cors": "^2.8.5", "express": "^4.17.3", + "express-list-endpoints": "^7.1.1", "nodemon": "^3.0.1" } } diff --git a/server.js b/server.js index f47771bd..8dfa5b9b 100644 --- a/server.js +++ b/server.js @@ -1,22 +1,118 @@ -import cors from "cors" -import express from "express" +import cors from "cors"; +import express from "express"; +import data from "./data.json"; +import listEndpoints from "express-list-endpoints"; -// 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() +/* console.log("Tweets here: ", data.length) */ + +const port = process.env.PORT || 8080; +const app = express(); // Add middlewares to enable cors and json body parsing -app.use(cors()) -app.use(express.json()) +app.use(cors()); +app.use(express.json()); -// Start defining your routes here +//List all enpoints app.get("/", (req, res) => { - res.send("Hello Technigo!") -}) + const endpoints = listEndpoints(app); + + res.json({ endpoints: endpoints }); +}); + +// Just to see all json data, temporary +app.get("/data", (req, res) => { + res.json(data); +}); + +//Find a message by id +app.get("/message/id/:id", (req, res) => { + const id = req.params.id; + + const messageById = data.find((item) => item._id === id); + + if (!messageById) { + return res + .status(404) + .json({ error: `Message with id ${id} doesn't exist` }); + } + + res.json(messageById); +}); + +//Endpoint to find all messages filtered by a year +/* app.get("/messages/year/:year", (req, res) => { + const createdAtDate = data.map((item) => item.createdAt); */ +/* res.json(createdAtYear); +}); */ + +//Endpoint to find all messages filtered by month +/* app.get("/messages/month/:month"); */ + +//Endpoint to sort all messages by date from old to new +/* app.get("/messages/?sort-by=date/old:-new:"); */ + +//Endpoint to filter all messages that have N hearts +app.get("/messages", (req, res) => { + const { hearts } = req.query; + + const heartsNumber = Number(hearts); + + console.log("hearts", heartsNumber); //http://localhost:8080/messages/?hearts=23 + + let filteredByHearts = data; + + if (hearts) { + filteredByHearts = filteredByHearts.filter( + (item) => item.hearts === heartsNumber, + ); + + if (!filteredByHearts.length) { + return res + .status(404) + .json({ error: `Message with ${heartsNumber} hearts doesn't exist` }); + } + } + + res.json(filteredByHearts); +}); + +//Find messages with specific number of hearts, same as previous one, temporary? +app.get("/messages/hearts/:hearts", (req, res) => { + const hearts = req.params.hearts; + const heartsNumber = data.find( + (heartsNumber) => Number(heartsNumber.hearts) === Number(hearts), + ); + + if (!heartsNumber) { + return res + .status(404) + .json({ error: `Message with ${hearts} number doesn't exist` }); + } + + res.json(heartsNumber); +}); + +//Endpoint to filter all messages that have N or more hearts +app.get("/messages/more-hearts", (req, res) => { + const { hearts } = req.query; + + const heartsMore = Number(hearts); + + let showPopular = data; + + if (hearts) { + showPopular = showPopular.filter((item) => item.hearts >= heartsMore); + + if (!showPopular.length) { + return res.status(404).json({ + error: `Message with more than ${hearts} hearts doesn't exist`, + }); + } + } + res.json(showPopular); +}); // Start the server app.listen(port, () => { - console.log(`Server running on http://localhost:${port}`) -}) + console.log(`Server running on http://localhost:${port}`); +}); From 76709f5c248936911bf263ceb948a9421dd5fa87 Mon Sep 17 00:00:00 2001 From: Julia Demianetc Date: Tue, 27 Jan 2026 04:19:32 +0100 Subject: [PATCH 2/9] added simple sorting by date, started to connect database and update endpoints, added POST --- package.json | 1 + server.js | 91 +++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 76 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index 3535ba4c..01cc00b0 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "cors": "^2.8.5", "express": "^4.17.3", "express-list-endpoints": "^7.1.1", + "mongoose": "^9.1.5", "nodemon": "^3.0.1" } } diff --git a/server.js b/server.js index 8dfa5b9b..e95d6831 100644 --- a/server.js +++ b/server.js @@ -2,6 +2,7 @@ import cors from "cors"; import express from "express"; import data from "./data.json"; import listEndpoints from "express-list-endpoints"; +import mongoose, { Model } from "mongoose"; /* console.log("Tweets here: ", data.length) */ @@ -12,6 +13,35 @@ const app = express(); app.use(cors()); app.use(express.json()); +//for database: +const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/thoughts"; +mongoose.connect(mongoUrl); //connecting to it +mongoose.Promise = Promise; + +// ---- Models ---- +//Thoughts' text +/* const Message = mongoose.model("ThoughtText", { message: String }); */ + +//Full thoughts' information +const Thought = mongoose.model("Thought", { + message: String /* { + type: mongoose.Schema.Types.ObjectId, + ref: "Message", + } */, + hearts: Number, + createdAt: { + type: Date, + default: () => new Date(), + }, +}); + +const User = mongoose.model("user", { + name: String, + email: String, +}); + +// ---- / Models ---- + //List all enpoints app.get("/", (req, res) => { const endpoints = listEndpoints(app); @@ -19,6 +49,18 @@ app.get("/", (req, res) => { res.json({ endpoints: endpoints }); }); +// ---- Endpoints POST ---- +//All thougths: +app.post("/thoughts", async (req, res) => { + const thought = new Thought(req.body); + await thought.save(); + res.json(thought); + /* console.log(req.body); + res.send("blahblah"); */ + /* const allThoughts = await Thought.find(); + res.json(allThoughts); */ +}); + // Just to see all json data, temporary app.get("/data", (req, res) => { res.json(data); @@ -39,25 +81,13 @@ app.get("/message/id/:id", (req, res) => { res.json(messageById); }); -//Endpoint to find all messages filtered by a year -/* app.get("/messages/year/:year", (req, res) => { - const createdAtDate = data.map((item) => item.createdAt); */ -/* res.json(createdAtYear); -}); */ - -//Endpoint to find all messages filtered by month -/* app.get("/messages/month/:month"); */ - -//Endpoint to sort all messages by date from old to new -/* app.get("/messages/?sort-by=date/old:-new:"); */ - -//Endpoint to filter all messages that have N hearts +//Filter all messages that have N hearts //url ex.: http://localhost:8080/messages/?hearts=23 app.get("/messages", (req, res) => { const { hearts } = req.query; const heartsNumber = Number(hearts); - console.log("hearts", heartsNumber); //http://localhost:8080/messages/?hearts=23 + console.log("hearts", heartsNumber); let filteredByHearts = data; @@ -76,7 +106,7 @@ app.get("/messages", (req, res) => { res.json(filteredByHearts); }); -//Find messages with specific number of hearts, same as previous one, temporary? +//Finds A MESSAGE (first one) with specific number of hearts, temporary app.get("/messages/hearts/:hearts", (req, res) => { const hearts = req.params.hearts; const heartsNumber = data.find( @@ -92,7 +122,7 @@ app.get("/messages/hearts/:hearts", (req, res) => { res.json(heartsNumber); }); -//Endpoint to filter all messages that have N or more hearts +//Endpoint to filter all messages that have N or more hearts, url ex.: http://localhost:8080/messages/more-hearts?hearts=N app.get("/messages/more-hearts", (req, res) => { const { hearts } = req.query; @@ -112,6 +142,35 @@ app.get("/messages/more-hearts", (req, res) => { res.json(showPopular); }); +//Endpoint to sort all messages by date from old to new, url ex.: /messages/sort-by/?date=old:-new +app.get("/messages/sort-oldest/", (req, res) => { + const sortedByDate = data.sort( + (a, b) => new Date(a.createdAt) - new Date(b.createdAt), + ); + + res.json(sortedByDate); +}); + +//Endpoint to find all messages filtered by date from a specific date that exists/up to a specific date +/* app.get("/messages/date/?date=old:-new); +app.get("/messages/date/?date=new:-old); +const { date } = req.query; + +const dateString = ParseInt(date); + +const DateObject = new Date(date)*/ + +//Endpoint to find all messages filtered by a year +/* app.get("/messages/year/:year", (req, res) => { + const createdAtDate = data.map((item) => item.createdAt); */ +/* res.json(createdAtYear); +}); */ + +//Endpoint to find all messages filtered by month +/* app.get("/messages/month/:month" or "/messages/month?month=May"); +use Date.parse for this to get timestamp with name of the month in it? +*/ + // Start the server app.listen(port, () => { console.log(`Server running on http://localhost:${port}`); From 9e0631e868c744b7c7d7620842f1049caa28ba17 Mon Sep 17 00:00:00 2001 From: Julia Demianetc Date: Tue, 27 Jan 2026 06:21:11 +0100 Subject: [PATCH 3/9] added buttons to update and to delete thought --- package.json | 1 + server.js | 11 +++++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 01cc00b0..a554ebe2 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "cors": "^2.8.5", "express": "^4.17.3", "express-list-endpoints": "^7.1.1", + "mongodb": "^7.0.0", "mongoose": "^9.1.5", "nodemon": "^3.0.1" } diff --git a/server.js b/server.js index e95d6831..aa1409f5 100644 --- a/server.js +++ b/server.js @@ -24,10 +24,11 @@ mongoose.Promise = Promise; //Full thoughts' information const Thought = mongoose.model("Thought", { - message: String /* { + message: String, + /* { type: mongoose.Schema.Types.ObjectId, ref: "Message", - } */, + } */ hearts: Number, createdAt: { type: Date, @@ -51,14 +52,12 @@ app.get("/", (req, res) => { // ---- Endpoints POST ---- //All thougths: -app.post("/thoughts", async (req, res) => { - const thought = new Thought(req.body); +app.post("/all", async (req, res) => { + const thought = new Thought({ message: req.body.message }); await thought.save(); res.json(thought); /* console.log(req.body); res.send("blahblah"); */ - /* const allThoughts = await Thought.find(); - res.json(allThoughts); */ }); // Just to see all json data, temporary From 576e6818b2761f1b330a9e70b64be74039d2873f Mon Sep 17 00:00:00 2001 From: Julia Demianetc Date: Fri, 30 Jan 2026 02:55:45 +0100 Subject: [PATCH 4/9] added mongoose models, updated all endpoints --- data.json | 2 +- server.js | 123 +++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 85 insertions(+), 40 deletions(-) diff --git a/data.json b/data.json index f0ec719c..5d075d28 100644 --- a/data.json +++ b/data.json @@ -17,7 +17,7 @@ "_id": "682e4f844fddf50010bbe738", "message": "The smell of coffee in the morning....", "hearts": 23, - "createdAt": "2025-05-22T22:11:16.075Z", + "createdAt": "2024-05-22T22:11:16.075Z", "__v": 0 }, { diff --git a/server.js b/server.js index aa1409f5..ac4f2112 100644 --- a/server.js +++ b/server.js @@ -2,7 +2,7 @@ import cors from "cors"; import express from "express"; import data from "./data.json"; import listEndpoints from "express-list-endpoints"; -import mongoose, { Model } from "mongoose"; +import mongoose, { Model, set } from "mongoose"; /* console.log("Tweets here: ", data.length) */ @@ -13,9 +13,9 @@ const app = express(); app.use(cors()); app.use(express.json()); -//for database: +//Connect database: const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/thoughts"; -mongoose.connect(mongoUrl); //connecting to it +mongoose.connect(mongoUrl); mongoose.Promise = Promise; // ---- Models ---- @@ -29,7 +29,7 @@ const Thought = mongoose.model("Thought", { type: mongoose.Schema.Types.ObjectId, ref: "Message", } */ - hearts: Number, + hearts: { type: Number, default: 0 }, createdAt: { type: Date, default: () => new Date(), @@ -43,16 +43,21 @@ const User = mongoose.model("user", { // ---- / Models ---- -//List all enpoints +//List all endpoints app.get("/", (req, res) => { const endpoints = listEndpoints(app); res.json({ endpoints: endpoints }); }); +// Just to see all json data, temporary +/* app.get("/data", (req, res) => { + res.json(data); +}); */ + // ---- Endpoints POST ---- //All thougths: -app.post("/all", async (req, res) => { +app.post("/thought", async (req, res) => { const thought = new Thought({ message: req.body.message }); await thought.save(); res.json(thought); @@ -60,13 +65,53 @@ app.post("/all", async (req, res) => { res.send("blahblah"); */ }); -// Just to see all json data, temporary -app.get("/data", (req, res) => { - res.json(data); +// ---- Endpoints PUT ---- + +//Edit a thought +app.put("/thought/:id", async (req, res) => { + const { id } = req.params; + const editedThought = req.body.message; + + const foundThought = await Thought.findById(id).exec(); + + if (foundThought) { + foundThought.message = editedThought; + await foundThought.save(); + } else { + res + .status(404) + .json({ error: `Oops, thought with ${id} doesn't seem to exist yet` }); + } +}); + +// ---- Endpoints DELETE ---- + +app.delete("/thought/:id", async (req, res) => { + const { id } = req.params; + + const foundThought = await Thought.findById(id).exec(); + + if (!foundThought) { + return res.status(404).json({ + error: `Oh no, you can't delete a thougth with ${id} because it doesn't exist!`, + }); + } + await foundThought.deleteOne().exec(); + res.status(200).json({ message: "Thought was deleted" }); }); -//Find a message by id -app.get("/message/id/:id", (req, res) => { +// ---- Endpoints GET ---- + +//All messages +/* app.get("/thoughts", async (req, res) => { + console.log("this has no params"); + const allThoughts = await Thought.find(); + + return res.json(allThoughts); +}); */ + +// ---- Find a message by id +app.get("/thought/:id", (req, res) => { const id = req.params.id; const messageById = data.find((item) => item._id === id); @@ -80,49 +125,38 @@ app.get("/message/id/:id", (req, res) => { res.json(messageById); }); -//Filter all messages that have N hearts //url ex.: http://localhost:8080/messages/?hearts=23 -app.get("/messages", (req, res) => { +// ---- All messages, filter: query param: filter by hearts N or =+N, url ex.: http://localhost:8080/thoughts?hearts=23, url ex.: http://localhost:8080/thoughts/more-hearts?hearts=N, +app.get("/thoughts", async (req, res) => { + /* console.log("this is the one with params"); */ const { hearts } = req.query; const heartsNumber = Number(hearts); - console.log("hearts", heartsNumber); + /* console.log("hearts", heartsNumber); */ - let filteredByHearts = data; + const query = Thought.find(); if (hearts) { - filteredByHearts = filteredByHearts.filter( - (item) => item.hearts === heartsNumber, - ); - - if (!filteredByHearts.length) { - return res - .status(404) - .json({ error: `Message with ${heartsNumber} hearts doesn't exist` }); - } + query.find({ + hearts: { $eq: heartsNumber }, + }); } - res.json(filteredByHearts); -}); - -//Finds A MESSAGE (first one) with specific number of hearts, temporary -app.get("/messages/hearts/:hearts", (req, res) => { - const hearts = req.params.hearts; - const heartsNumber = data.find( - (heartsNumber) => Number(heartsNumber.hearts) === Number(hearts), - ); + const allThoughts = await query.exec(); - if (!heartsNumber) { + if (!allThoughts.length) { return res .status(404) - .json({ error: `Message with ${hearts} number doesn't exist` }); + .json({ error: `Message with ${heartsNumber} hearts doesn't exist` }); } - res.json(heartsNumber); + res.json(allThoughts); }); -//Endpoint to filter all messages that have N or more hearts, url ex.: http://localhost:8080/messages/more-hearts?hearts=N -app.get("/messages/more-hearts", (req, res) => { +// TODO ---- LATER ----- + +// --- All messages that have N or more hearts, url ex.: http://localhost:8080/thoughts/more-hearts?hearts=N +app.get("/thoughts/more-hearts", (req, res) => { const { hearts } = req.query; const heartsMore = Number(hearts); @@ -141,8 +175,10 @@ app.get("/messages/more-hearts", (req, res) => { res.json(showPopular); }); +// ---- Sorting by date ---- + //Endpoint to sort all messages by date from old to new, url ex.: /messages/sort-by/?date=old:-new -app.get("/messages/sort-oldest/", (req, res) => { +app.get("/thoughts/sort-oldest/", (req, res) => { const sortedByDate = data.sort( (a, b) => new Date(a.createdAt) - new Date(b.createdAt), ); @@ -150,6 +186,15 @@ app.get("/messages/sort-oldest/", (req, res) => { res.json(sortedByDate); }); +//Endpoint to sort all messages by date new to old, url ex.: /messages/sort-by/?date=old:-new +app.get("/thoughts/sort-newest/", (req, res) => { + const sortedByDate = data.sort( + (a, b) => new Date(b.createdAt) - new Date(a.createdAt), + ); + + res.json(sortedByDate); +}); + //Endpoint to find all messages filtered by date from a specific date that exists/up to a specific date /* app.get("/messages/date/?date=old:-new); app.get("/messages/date/?date=new:-old); From 0f356feaaff86970410cf6a12299c9a4a85648b4 Mon Sep 17 00:00:00 2001 From: Julia Demianetc Date: Fri, 30 Jan 2026 10:56:28 +0100 Subject: [PATCH 5/9] updated post, added error handling --- .vscode/settings.json | 22 +++++++++++ server.js | 87 ++++++++++++++++++++++++++++--------------- 2 files changed, 78 insertions(+), 31 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..d1f4512c --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,22 @@ +{ + "workbench.colorCustomizations": { + "activityBar.activeBackground": "#2f7c47", + "activityBar.background": "#2f7c47", + "activityBar.foreground": "#e7e7e7", + "activityBar.inactiveForeground": "#e7e7e799", + "activityBarBadge.background": "#422c74", + "activityBarBadge.foreground": "#e7e7e7", + "commandCenter.border": "#e7e7e799", + "sash.hoverBorder": "#2f7c47", + "statusBar.background": "#215732", + "statusBar.foreground": "#e7e7e7", + "statusBarItem.hoverBackground": "#2f7c47", + "statusBarItem.remoteBackground": "#215732", + "statusBarItem.remoteForeground": "#e7e7e7", + "titleBar.activeBackground": "#215732", + "titleBar.activeForeground": "#e7e7e7", + "titleBar.inactiveBackground": "#21573299", + "titleBar.inactiveForeground": "#e7e7e799" + }, + "peacock.color": "#215732" +} diff --git a/server.js b/server.js index ac4f2112..559fc03b 100644 --- a/server.js +++ b/server.js @@ -24,12 +24,16 @@ mongoose.Promise = Promise; //Full thoughts' information const Thought = mongoose.model("Thought", { - message: String, - /* { - type: mongoose.Schema.Types.ObjectId, - ref: "Message", - } */ - hearts: { type: Number, default: 0 }, + message: { + type: String, + required: true, + minLength: 5, + maxLength: 140, + }, + hearts: { + type: Number, + default: 0, + }, createdAt: { type: Date, default: () => new Date(), @@ -56,11 +60,20 @@ app.get("/", (req, res) => { }); */ // ---- Endpoints POST ---- -//All thougths: -app.post("/thought", async (req, res) => { - const thought = new Thought({ message: req.body.message }); - await thought.save(); - res.json(thought); +//Post a thought: +app.post("/thoughts", async (req, res) => { + const { message } = req.body; + const thought = new Thought({ message }); + + try { + const savedThought = await thought.save(); + res.status(201).json(savedThought); + } catch (err) { + res.status(404).json({ + message: "Couldn't save a thought to the database", + error: err.errors, //check the errors + }); + } /* console.log(req.body); res.send("blahblah"); */ }); @@ -73,10 +86,12 @@ app.put("/thought/:id", async (req, res) => { const editedThought = req.body.message; const foundThought = await Thought.findById(id).exec(); + console.log({ foundThought }); if (foundThought) { foundThought.message = editedThought; await foundThought.save(); + // TODO response } else { res .status(404) @@ -85,7 +100,7 @@ app.put("/thought/:id", async (req, res) => { }); // ---- Endpoints DELETE ---- - +// Delete a thought app.delete("/thought/:id", async (req, res) => { const { id } = req.params; @@ -110,21 +125,6 @@ app.delete("/thought/:id", async (req, res) => { return res.json(allThoughts); }); */ -// ---- Find a message by id -app.get("/thought/:id", (req, res) => { - const id = req.params.id; - - const messageById = data.find((item) => item._id === id); - - if (!messageById) { - return res - .status(404) - .json({ error: `Message with id ${id} doesn't exist` }); - } - - res.json(messageById); -}); - // ---- All messages, filter: query param: filter by hearts N or =+N, url ex.: http://localhost:8080/thoughts?hearts=23, url ex.: http://localhost:8080/thoughts/more-hearts?hearts=N, app.get("/thoughts", async (req, res) => { /* console.log("this is the one with params"); */ @@ -132,11 +132,10 @@ app.get("/thoughts", async (req, res) => { const heartsNumber = Number(hearts); - /* console.log("hearts", heartsNumber); */ - - const query = Thought.find(); + const query = Thought.find().sort({ createdAt: "desc" }); //building query for filtering by amount of hearts if (hearts) { + // query.find({ hearts: { $eq: heartsNumber }, }); @@ -153,6 +152,21 @@ app.get("/thoughts", async (req, res) => { res.json(allThoughts); }); +// ---- Find a message by id +app.get("/thought/:id", (req, res) => { + const id = req.params.id; + + const messageById = data.find((item) => item._id === id); // TODO still data + + if (!messageById) { + return res + .status(404) + .json({ error: `Message with id ${id} doesn't exist` }); + } + + res.json(messageById); +}); + // TODO ---- LATER ----- // --- All messages that have N or more hearts, url ex.: http://localhost:8080/thoughts/more-hearts?hearts=N @@ -161,7 +175,7 @@ app.get("/thoughts/more-hearts", (req, res) => { const heartsMore = Number(hearts); - let showPopular = data; + let showPopular = data; // TODO Still data if (hearts) { showPopular = showPopular.filter((item) => item.hearts >= heartsMore); @@ -180,6 +194,7 @@ app.get("/thoughts/more-hearts", (req, res) => { //Endpoint to sort all messages by date from old to new, url ex.: /messages/sort-by/?date=old:-new app.get("/thoughts/sort-oldest/", (req, res) => { const sortedByDate = data.sort( + // TODO Still data (a, b) => new Date(a.createdAt) - new Date(b.createdAt), ); @@ -189,6 +204,7 @@ app.get("/thoughts/sort-oldest/", (req, res) => { //Endpoint to sort all messages by date new to old, url ex.: /messages/sort-by/?date=old:-new app.get("/thoughts/sort-newest/", (req, res) => { const sortedByDate = data.sort( + // TODO still data (a, b) => new Date(b.createdAt) - new Date(a.createdAt), ); @@ -219,3 +235,12 @@ use Date.parse for this to get timestamp with name of the month in it? app.listen(port, () => { console.log(`Server running on http://localhost:${port}`); }); + +// ---- LIKE ---- +// TODO add like to a post + +// ---- REGISTER ---- +// TODO add user registration + +// ---- LOGIN ---- +// TODO add user login From 9fd8edf2338c5988ee2718d7f1d41dba0f10667a Mon Sep 17 00:00:00 2001 From: Julia Demianetc Date: Sat, 7 Feb 2026 13:19:16 +0100 Subject: [PATCH 6/9] Updated CRUDs, all are working, swirched from hardcoded data to database --- server.js | 295 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 201 insertions(+), 94 deletions(-) diff --git a/server.js b/server.js index 559fc03b..55a28ed9 100644 --- a/server.js +++ b/server.js @@ -19,8 +19,6 @@ mongoose.connect(mongoUrl); mongoose.Promise = Promise; // ---- Models ---- -//Thoughts' text -/* const Message = mongoose.model("ThoughtText", { message: String }); */ //Full thoughts' information const Thought = mongoose.model("Thought", { @@ -40,161 +38,273 @@ const Thought = mongoose.model("Thought", { }, }); -const User = mongoose.model("user", { - name: String, - email: String, +const User = mongoose.model("User", { + name: { + type: String, + required: true, + minLength: 4, + maxLength: 32, + match: true, + }, + email: { + type: String, + required: true, + match: true, + unique: true, + }, + password: { + type: String, + required: true, + minLength: 8, + maxLength: 24, + match: true, + }, + registerDate: { + type: Date, + default: () => new Date(), + }, }); // ---- / Models ---- -//List all endpoints +// ---- List all endpoints app.get("/", (req, res) => { const endpoints = listEndpoints(app); res.json({ endpoints: endpoints }); }); -// Just to see all json data, temporary -/* app.get("/data", (req, res) => { - res.json(data); -}); */ - // ---- Endpoints POST ---- -//Post a thought: +// ---- Post a thought: app.post("/thoughts", async (req, res) => { const { message } = req.body; - const thought = new Thought({ message }); try { - const savedThought = await thought.save(); - res.status(201).json(savedThought); + const thought = await new Thought({ message }).save(); + res.status(201).json(thought); } catch (err) { - res.status(404).json({ + //Bad request + res.status(400).json({ message: "Couldn't save a thought to the database", error: err.errors, //check the errors }); } - /* console.log(req.body); - res.send("blahblah"); */ }); -// ---- Endpoints PUT ---- +// ---- / Endpoints POST ---- -//Edit a thought -app.put("/thought/:id", async (req, res) => { - const { id } = req.params; - const editedThought = req.body.message; +// ---- Endpoints GET ---- +// ---- All messages, and filter: query param: filter by hearts N url ex.: http://localhost:8080/thoughts?hearts=23 +app.get("/thoughts", async (req, res) => { + /* console.log("this is the one with params"); */ + const { hearts } = req.query; - const foundThought = await Thought.findById(id).exec(); - console.log({ foundThought }); + const heartsNumber = Number(hearts); - if (foundThought) { - foundThought.message = editedThought; - await foundThought.save(); - // TODO response - } else { - res - .status(404) - .json({ error: `Oops, thought with ${id} doesn't seem to exist yet` }); + const query = Thought.find().sort({ createdAt: "desc" }); //building query for filtering by amount of hearts + try { + if (hearts) { + //Filter by amount of hearts + query.find({ + hearts: { $eq: heartsNumber }, + }); + } + + const allThoughts = await query.exec(); + + if (!allThoughts.length) { + return res + .status(404) + .json({ error: `Message with ${heartsNumber} hearts doesn't exist` }); + } + + res.json(allThoughts); + } catch (err) { + res.status(400).json({ + message: "On no, something went wrong, couldn't retrieve any thoughts", + }); } }); -// ---- Endpoints DELETE ---- -// Delete a thought -app.delete("/thought/:id", async (req, res) => { +// ---- Find one thought by id +app.get("/thoughts/:id", async (req, res) => { const { id } = req.params; - const foundThought = await Thought.findById(id).exec(); + if (!mongoose.Types.ObjectId.isValid(id)) { + return res.status(400).json({ error: `Oops, this id ${id} is invalid` }); + } + + try { + const singleThought = await Thought.findById(id).exec(); + + if (!singleThought) { + return res.status(404).json({ + error: `Oh no, seem like a thougth with ${id} doesn't exist or was deleted!`, + }); + } - if (!foundThought) { - return res.status(404).json({ - error: `Oh no, you can't delete a thougth with ${id} because it doesn't exist!`, + res.status(201).json(singleThought); + } catch (err) { + res.status(404).json({ + message: `Oops, thought with ${id} doesn't seem to exist yet`, + error: err.errors, }); } - await foundThought.deleteOne().exec(); - res.status(200).json({ message: "Thought was deleted" }); }); -// ---- Endpoints GET ---- +// ---- Like a thought +app.post("/thoughts/:id/like", async (req, res) => { + const { id } = req.params; + const update = { $inc: { hearts: 1 }, new: true }; -//All messages -/* app.get("/thoughts", async (req, res) => { - console.log("this has no params"); - const allThoughts = await Thought.find(); + if (!mongoose.Types.ObjectId.isValid(id)) { + return res.status(404).json({ error: `Oops, this id ${id} is invalid` }); + } - return res.json(allThoughts); -}); */ + try { + const addLike = await Thought.findByIdAndUpdate(id, update); -// ---- All messages, filter: query param: filter by hearts N or =+N, url ex.: http://localhost:8080/thoughts?hearts=23, url ex.: http://localhost:8080/thoughts/more-hearts?hearts=N, -app.get("/thoughts", async (req, res) => { - /* console.log("this is the one with params"); */ - const { hearts } = req.query; + if (!addLike) { + return res.status(404).json({ + error: `Oops, can't like thought with id ${id} because it doesn't exist or was deleted`, + }); + } - const heartsNumber = Number(hearts); + res.status(200).json(addLike); + } catch (err) { + res.status(500).json({ + message: "Couldn't save like to the database", + error: err.errors, + }); + } +}); - const query = Thought.find().sort({ createdAt: "desc" }); //building query for filtering by amount of hearts +// --- All messages with filter: query param, that have N or more hearts, url ex.: http://localhost:8080/thoughts/hearts?hearts=N&sort=desc +// TODO check the route +app.get("/hearts", async (req, res) => { + const { hearts } = req.query; + const heartsMore = Number(hearts); + + if (isNaN(heartsMore)) { + return res + .status(400) + .json({ message: "Oops, this number of likes is not valid" }); + } + + const query = {}; if (hearts) { - // - query.find({ - hearts: { $eq: heartsNumber }, - }); + query.hearts = { $gte: heartsMore }; } - const allThoughts = await query.exec(); + try { + const filteredThougths = await Thought.find(query).sort({ hearts: "desc" }); - if (!allThoughts.length) { - return res - .status(404) - .json({ error: `Message with ${heartsNumber} hearts doesn't exist` }); + if (filteredThougths.length === 0) { + return res.status(404).json({ + success: false, + response: [], + message: `Looks like there are no thoughts with ${hearts} or more likes.`, + }); + } + return res.status(200).json({ + success: true, + response: filteredThougths, + message: "Found them!", + }); + } catch (err) { + return res.status(500).json({ + success: false, + response: [], + message: "Something went wrong at the server", + }); } +}); + +// ---- / Endpoints GET ---- - res.json(allThoughts); +// TODO --- Edit thought ----- +// ---- Endpoints PUT ---- +//Edit a thought + +app.put("/test/:id", async (req, res) => { + return res.json(req.body); }); -// ---- Find a message by id -app.get("/thought/:id", (req, res) => { - const id = req.params.id; +app.put("/thoughts/:id", async (req, res) => { + const { id } = req.params; + const editedThought = req.body.message; - const messageById = data.find((item) => item._id === id); // TODO still data + if (!mongoose.Types.ObjectId.isValid(id)) { + return res.status(400).json({ error: `Oops, this id ${id} is invalid` }); + } - if (!messageById) { - return res - .status(404) - .json({ error: `Message with id ${id} doesn't exist` }); + if (!editedThought) { + return res.status(400).json({ + error: "Message is required to update a thought", + }); } - res.json(messageById); + const foundThought = await Thought.findById(id); + try { + if (!foundThought) { + return res.status(404).json({ + error: `Oops, thought with ${id} doesn't seem to exist yet`, + }); + } + foundThought.message = editedThought; + await foundThought.save(); + res.status(200).json({ + message: "Message was successfully updated", + thought: foundThought, + }); + } catch (err) { + res.status(500).json({ + message: "Something went wrong at the server", + error: err.errors, + }); + } }); -// TODO ---- LATER ----- - -// --- All messages that have N or more hearts, url ex.: http://localhost:8080/thoughts/more-hearts?hearts=N -app.get("/thoughts/more-hearts", (req, res) => { - const { hearts } = req.query; +// ---- / Endpoints PUT ---- - const heartsMore = Number(hearts); - - let showPopular = data; // TODO Still data +// ---- Endpoints DELETE ---- +// Delete a thought +app.delete("/thoughts/:id", async (req, res) => { + const { id } = req.params; - if (hearts) { - showPopular = showPopular.filter((item) => item.hearts >= heartsMore); + if (!mongoose.Types.ObjectId.isValid(id)) { + return res.status(400).json({ error: "Oops, looks like id is invalid" }); + } + try { + const foundThought = await Thought.findByIdAndDelete(id).exec(); - if (!showPopular.length) { + if (!foundThought) { return res.status(404).json({ - error: `Message with more than ${hearts} hearts doesn't exist`, + error: `Oh no, you can't delete a thougth with ${id} because it doesn't exist!`, }); } + + res.status(200).json({ message: "Thought was deleted" }); + } catch (err) { + res.status(500).json({ + message: "Something went wrong at the server", + error: err.errors, + }); } - res.json(showPopular); }); +// ---- / Endpoints DELETE ---- + +// TODO ---- LATER ----- + // ---- Sorting by date ---- -//Endpoint to sort all messages by date from old to new, url ex.: /messages/sort-by/?date=old:-new -app.get("/thoughts/sort-oldest/", (req, res) => { - const sortedByDate = data.sort( - // TODO Still data +//Endpoint to sort all messages by date from old to new, url ex.: OR with /sort-by/?date=old:-new +app.get("/sort-oldest/", async (req, res) => { + /* const { date } = req.query; */ + + const sortedByDate = await new Thought.sort( (a, b) => new Date(a.createdAt) - new Date(b.createdAt), ); @@ -236,9 +346,6 @@ app.listen(port, () => { console.log(`Server running on http://localhost:${port}`); }); -// ---- LIKE ---- -// TODO add like to a post - // ---- REGISTER ---- // TODO add user registration From 391ef2b82a1d92e2c804ef075955eb8832756a36 Mon Sep 17 00:00:00 2001 From: Julia Demianetc Date: Sun, 8 Feb 2026 21:30:29 +0100 Subject: [PATCH 7/9] Added authorization routes, protected some CRUDS with authenticaton --- package.json | 5 ++ server.js | 189 ++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 155 insertions(+), 39 deletions(-) diff --git a/package.json b/package.json index a554ebe2..a0e42e81 100644 --- a/package.json +++ b/package.json @@ -13,11 +13,16 @@ "@babel/core": "^7.17.9", "@babel/node": "^7.16.8", "@babel/preset-env": "^7.16.11", + "bcrypt": "^6.0.0", + "bcrypt-nodejs": "^0.0.3", "cors": "^2.8.5", "express": "^4.17.3", "express-list-endpoints": "^7.1.1", "mongodb": "^7.0.0", "mongoose": "^9.1.5", "nodemon": "^3.0.1" + }, + "devDependencies": { + "@types/bcrypt-nodejs": "^0.0.31" } } diff --git a/server.js b/server.js index 55a28ed9..1d7e7d15 100644 --- a/server.js +++ b/server.js @@ -3,6 +3,8 @@ import express from "express"; import data from "./data.json"; import listEndpoints from "express-list-endpoints"; import mongoose, { Model, set } from "mongoose"; +import crypto from "crypto"; +import bcrypt from "bcrypt-nodejs"; /* console.log("Tweets here: ", data.length) */ @@ -41,42 +43,148 @@ const Thought = mongoose.model("Thought", { const User = mongoose.model("User", { name: { type: String, + unique: true, required: true, minLength: 4, maxLength: 32, - match: true, }, + email: { type: String, required: true, - match: true, unique: true, }, + password: { type: String, required: true, - minLength: 8, - maxLength: 24, - match: true, }, + + accessToken: { + type: String, + default: () => crypto.randomBytes(128).toString("hex"), + }, + registerDate: { type: Date, default: () => new Date(), }, }); - // ---- / Models ---- -// ---- List all endpoints +// ---- Authentication function: only authorised users can add or like thoughts + +const authenticateUser = async (req, res, next) => { + const user = await User.findOne({ + accessToken: req.header("Authorization"), + }); + if (user) { + req.user = user; + next(); + } else { + //user is matched and not authorized to do smth + res.status(401).json({ loggedOut: true }); + } +}; +// ---- // Authentication function + +// ---- List all endpoints ---- app.get("/", (req, res) => { const endpoints = listEndpoints(app); res.json({ endpoints: endpoints }); }); +// TODO ---- ALL USER AUTHORISATION ROUTES + +// TODO delete this // ---- Secrets EXAMPLE ---- +//app.get("/secrets", authenticateUser); +app.get("/secrets", authenticateUser, (req, res) => { + res.json({ secret: "This is secret" }); + /* fetch("...", { headers: { Authorisation: "my secret api key" } }); */ + //res.send(process.env.API_KEY) - in that cituation, environment variable is being sent to user and is open, even though it is not in the code, but is env variable that was created by me +}); + +// TODO // ----Creating new user, route: /register---- + +app.post("/register", async (req, res) => { + try { + const { name, email, password } = req.body; + + if (!name || !email || !password) { + return res.status(400).json({ + message: "All fields are required to register a user", + }); + } + + if (password.length < 8) { + return res + .status(400) + .json({ message: "Password must be at least 8 characters long" }); + } + + const salt = bcrypt.genSaltSync(); + const hashedPass = bcrypt.hashSync(password, salt); + + const user = new User({ + name, + email, + password: hashedPass, + }); + + await user.save(); + + res.status(201).json({ + id: user._id, + accessToken: user.accessToken, + }); //encrypting passwords + } catch (err) { + //User with this name already exists + if (err.code === 11000) { + return res + .status(400) + .json({ message: "User with this name or email alredy exists" }); + } + //Bad request + res + .status(400) + .json({ message: "Couldn't create a user", error: err.errors }); + } +}); + +// TODO // ---- Access with existing user, route: /login ---- +app.post("/login", async (req, res) => { + try { + const { email, password } = req.body; + + if (!email || !password) { + return res.status(400).json({ + message: "All fields are required to login", + }); + } + + const user = await User.findOne({ email }); //retrieving username from database, lookig for match by email that should be unique (1 email=1 user) + + if (!user || !bcrypt.compareSync(password, user.password)) { + return res.status(401).json({ message: "Invalid email or password" }); + } + res.json({ userId: user._id, accessToken: user.accessToken }); + } catch (err) { + //Bad request: + // 1. Email is incorrect + // 2. password doesn't match + res.status(500).json({ + message: "Something went wrong, please try agan", + error: err.errors, + }); + } +}); + // ---- Endpoints POST ---- // ---- Post a thought: -app.post("/thoughts", async (req, res) => { +// TODO // app.post("/thoughts", authenticateUser); //giving only authorised users rights to create thoughts +app.post("/thoughts", authenticateUser, async (req, res) => { + //This will only work if next() function is called from the authenticateUser const { message } = req.body; try { @@ -91,6 +199,36 @@ app.post("/thoughts", async (req, res) => { } }); +// ---- Like a thought +app.post("/thoughts/:id/like", async (req, res) => { + const { id } = req.params; + + //Storing operator in variable and options in variables + const update = { $inc: { hearts: 1 } }; + const options = { new: true, runValidators: true }; + + if (!mongoose.Types.ObjectId.isValid(id)) { + return res.status(404).json({ error: `Oops, this id ${id} is invalid` }); + } + + try { + const addLike = await Thought.findByIdAndUpdate(id, update, options); + + if (!addLike) { + return res.status(404).json({ + error: `Oops, can't like thought with id ${id} because it doesn't exist or was deleted`, + }); + } + + res.status(200).json(addLike); + } catch (err) { + res.status(500).json({ + message: "Couldn't save like to the database", + error: err.errors, + }); + } +}); + // ---- / Endpoints POST ---- // ---- Endpoints GET ---- @@ -152,33 +290,6 @@ app.get("/thoughts/:id", async (req, res) => { } }); -// ---- Like a thought -app.post("/thoughts/:id/like", async (req, res) => { - const { id } = req.params; - const update = { $inc: { hearts: 1 }, new: true }; - - if (!mongoose.Types.ObjectId.isValid(id)) { - return res.status(404).json({ error: `Oops, this id ${id} is invalid` }); - } - - try { - const addLike = await Thought.findByIdAndUpdate(id, update); - - if (!addLike) { - return res.status(404).json({ - error: `Oops, can't like thought with id ${id} because it doesn't exist or was deleted`, - }); - } - - res.status(200).json(addLike); - } catch (err) { - res.status(500).json({ - message: "Couldn't save like to the database", - error: err.errors, - }); - } -}); - // --- All messages with filter: query param, that have N or more hearts, url ex.: http://localhost:8080/thoughts/hearts?hearts=N&sort=desc // TODO check the route @@ -227,11 +338,11 @@ app.get("/hearts", async (req, res) => { // ---- Endpoints PUT ---- //Edit a thought -app.put("/test/:id", async (req, res) => { +/* app.put("/test/:id", async (req, res) => { return res.json(req.body); -}); +}); */ -app.put("/thoughts/:id", async (req, res) => { +app.put("/thoughts/:id", authenticateUser, async (req, res) => { const { id } = req.params; const editedThought = req.body.message; @@ -270,7 +381,7 @@ app.put("/thoughts/:id", async (req, res) => { // ---- Endpoints DELETE ---- // Delete a thought -app.delete("/thoughts/:id", async (req, res) => { +app.delete("/thoughts/:id", authenticateUser, async (req, res) => { const { id } = req.params; if (!mongoose.Types.ObjectId.isValid(id)) { From 6c5642be8d28ea57665ed3b736c4166667abde56 Mon Sep 17 00:00:00 2001 From: Julia Demianetc Date: Sun, 8 Feb 2026 23:45:38 +0100 Subject: [PATCH 8/9] Clean up --- server.js | 100 ++++++------------------------------------------------ 1 file changed, 11 insertions(+), 89 deletions(-) diff --git a/server.js b/server.js index 1d7e7d15..5abe2a35 100644 --- a/server.js +++ b/server.js @@ -75,9 +75,12 @@ const User = mongoose.model("User", { // ---- Authentication function: only authorised users can add or like thoughts const authenticateUser = async (req, res, next) => { - const user = await User.findOne({ - accessToken: req.header("Authorization"), - }); + const user = await User.findOne; + const token = req.header("Authorization"); + if (!token) { + return res.status(401).json({ message: "User is logged out" }); + } + if (user) { req.user = user; next(); @@ -95,17 +98,9 @@ app.get("/", (req, res) => { res.json({ endpoints: endpoints }); }); -// TODO ---- ALL USER AUTHORISATION ROUTES +// ---- ALL USER AUTHORISATION ROUTES -// TODO delete this // ---- Secrets EXAMPLE ---- -//app.get("/secrets", authenticateUser); -app.get("/secrets", authenticateUser, (req, res) => { - res.json({ secret: "This is secret" }); - /* fetch("...", { headers: { Authorisation: "my secret api key" } }); */ - //res.send(process.env.API_KEY) - in that cituation, environment variable is being sent to user and is open, even though it is not in the code, but is env variable that was created by me -}); - -// TODO // ----Creating new user, route: /register---- +// ----Creating new user, route: /register---- app.post("/register", async (req, res) => { try { @@ -152,7 +147,7 @@ app.post("/register", async (req, res) => { } }); -// TODO // ---- Access with existing user, route: /login ---- +// ---- Access with existing user, route: /login ---- app.post("/login", async (req, res) => { try { const { email, password } = req.body; @@ -182,7 +177,6 @@ app.post("/login", async (req, res) => { // ---- Endpoints POST ---- // ---- Post a thought: -// TODO // app.post("/thoughts", authenticateUser); //giving only authorised users rights to create thoughts app.post("/thoughts", authenticateUser, async (req, res) => { //This will only work if next() function is called from the authenticateUser const { message } = req.body; @@ -292,56 +286,11 @@ app.get("/thoughts/:id", async (req, res) => { // --- All messages with filter: query param, that have N or more hearts, url ex.: http://localhost:8080/thoughts/hearts?hearts=N&sort=desc -// TODO check the route -app.get("/hearts", async (req, res) => { - const { hearts } = req.query; - const heartsMore = Number(hearts); - - if (isNaN(heartsMore)) { - return res - .status(400) - .json({ message: "Oops, this number of likes is not valid" }); - } - - const query = {}; - if (hearts) { - query.hearts = { $gte: heartsMore }; - } - - try { - const filteredThougths = await Thought.find(query).sort({ hearts: "desc" }); - - if (filteredThougths.length === 0) { - return res.status(404).json({ - success: false, - response: [], - message: `Looks like there are no thoughts with ${hearts} or more likes.`, - }); - } - return res.status(200).json({ - success: true, - response: filteredThougths, - message: "Found them!", - }); - } catch (err) { - return res.status(500).json({ - success: false, - response: [], - message: "Something went wrong at the server", - }); - } -}); - // ---- / Endpoints GET ---- -// TODO --- Edit thought ----- // ---- Endpoints PUT ---- -//Edit a thought - -/* app.put("/test/:id", async (req, res) => { - return res.json(req.body); -}); */ +//Edit a thought app.put("/thoughts/:id", authenticateUser, async (req, res) => { const { id } = req.params; const editedThought = req.body.message; @@ -413,9 +362,8 @@ app.delete("/thoughts/:id", authenticateUser, async (req, res) => { //Endpoint to sort all messages by date from old to new, url ex.: OR with /sort-by/?date=old:-new app.get("/sort-oldest/", async (req, res) => { - /* const { date } = req.query; */ - const sortedByDate = await new Thought.sort( + // TODO still data (a, b) => new Date(a.createdAt) - new Date(b.createdAt), ); @@ -432,33 +380,7 @@ app.get("/thoughts/sort-newest/", (req, res) => { res.json(sortedByDate); }); -//Endpoint to find all messages filtered by date from a specific date that exists/up to a specific date -/* app.get("/messages/date/?date=old:-new); -app.get("/messages/date/?date=new:-old); -const { date } = req.query; - -const dateString = ParseInt(date); - -const DateObject = new Date(date)*/ - -//Endpoint to find all messages filtered by a year -/* app.get("/messages/year/:year", (req, res) => { - const createdAtDate = data.map((item) => item.createdAt); */ -/* res.json(createdAtYear); -}); */ - -//Endpoint to find all messages filtered by month -/* app.get("/messages/month/:month" or "/messages/month?month=May"); -use Date.parse for this to get timestamp with name of the month in it? -*/ - // Start the server app.listen(port, () => { console.log(`Server running on http://localhost:${port}`); }); - -// ---- REGISTER ---- -// TODO add user registration - -// ---- LOGIN ---- -// TODO add user login From 66d96c280c0fbfa443c9c1f52f6526b7a9b35ba0 Mon Sep 17 00:00:00 2001 From: Julia Demianetc Date: Sun, 8 Feb 2026 23:55:13 +0100 Subject: [PATCH 9/9] updated readme --- README.md | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 0f9f073d..59fa8685 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,7 @@ -# Project API - -This project includes the packages and babel setup for an express server, and is just meant to make things a little simpler to get up and running with. +Backend: https://get-thoughts-out-api.onrender.com -## Getting started +Full demo on Happy Thoughts: https://happy-thoughts-byjd.netlify.app/ -Install dependencies with `npm install`, then start the server by running `npm run dev` - -## View it live +# Project API -Every project should be deployed somewhere. Be sure to include the link to the deployed project so that the viewer can click around and see what it's all about. +This project includes the packages and babel setup for an express server, and is just meant to make things a little simpler to get up and running with.