-
Notifications
You must be signed in to change notification settings - Fork 514
Wen's happy thoughts API #485
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4ddee8f
e687a3b
cc9ed49
276add1
71e9b4c
8a57f1f
6075cf5
9de148e
e6fb3a4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,18 @@ | ||
| # Project Happy Thoughts API | ||
|
|
||
| Replace this readme with your own information about your project. | ||
| This project builds the backend for [Happy Thoughts project](https://github.com/wwenzz/project-happy-thoughts-vite) by creating RESTful API. This backend has the following endpoints: | ||
|
|
||
| Start by briefly describing the assignment in a sentence or two. Keep it short and to the point. | ||
| - "/": Display a list of endpoints served by the backend. | ||
| - "/thoughts": Offer GET and POST requests that display all thoughts and post a single thought individually. | ||
| - "/thoughts/:id/like": Like a post based on the post id. Always increment by 1. | ||
| - "/thoughts/:id/unlike": Unlike a post based on the post id. Always decrement by 1 and cannot apply on posts with 0 hearts. | ||
|
|
||
| ## The problem | ||
|
|
||
| Describe how you approached to problem, and what tools and techniques you used to solve it. How did you plan? What technologies did you use? If you had more time, what would be next? | ||
| - POST request: Retreived the request body and used mongoose findByIdAndUpdate as well as findOneAndUpdate methods to post new data. | ||
| - Error handling: Implemented try and catch block to catch any potential errors and further customise the error messages. | ||
| - Response limit & sorting: Applied limit and sort methods from mongoose to limit and sort the responses. | ||
|
|
||
| ## View it live | ||
|
|
||
| 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. | ||
| https://wen-happy-thoughts-api.onrender.com/ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| 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, | ||
| required: false, | ||
| min: 0, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mm, I see what's coming 😉 |
||
| }, | ||
| createdAt: { | ||
| type: Date, | ||
| default: Date.now, | ||
| required: false, | ||
| }, | ||
| }); | ||
|
|
||
| const Thought = model("Thought", thoughtSchema); | ||
|
|
||
| export default Thought; | ||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,12 @@ | ||
| import cors from "cors"; | ||
| import express from "express"; | ||
| import expressListEndpoints from "express-list-endpoints"; | ||
| import mongoose from "mongoose"; | ||
|
|
||
| const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/project-mongo"; | ||
| import Thought from "./models/Thought"; | ||
|
|
||
| const mongoUrl = | ||
| process.env.MONGO_URL || "mongodb://localhost/project-happy-thoughts"; | ||
| mongoose.connect(mongoUrl); | ||
| mongoose.Promise = Promise; | ||
|
|
||
|
|
@@ -18,7 +22,89 @@ app.use(express.json()); | |
|
|
||
| // Start defining your routes here | ||
| app.get("/", (req, res) => { | ||
| res.send("Hello Technigo!"); | ||
| const endpoints = expressListEndpoints(app); | ||
| res.json(endpoints); | ||
| }); | ||
|
|
||
| // Get all thoughts | ||
| app.get("/thoughts", async (req, res) => { | ||
| const thoughts = await Thought.find() | ||
| .sort({ createdAt: -1 }) | ||
| .limit(20) | ||
| .exec(); | ||
| res.json(thoughts); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A status code would be nice here |
||
| }); | ||
|
|
||
| // Post a thought | ||
| app.post("/thoughts", async (req, res) => { | ||
| const { message } = req.body; | ||
| try { | ||
| if (message) { | ||
| const newThought = await new Thought({ message }).save(); | ||
| res.status(201).json(newThought); | ||
| } else { | ||
| throw new Error("No message input..."); | ||
| } | ||
| } catch (error) { | ||
| res.status(400).json({ | ||
| success: false, | ||
| error: error.message, | ||
| message: "Could not save the thought...", | ||
| }); | ||
| } | ||
| }); | ||
|
|
||
| // Like a post | ||
| app.post("/thoughts/:thoughtId/like", async (req, res) => { | ||
| const { thoughtId } = req.params; | ||
| try { | ||
| const post = await Thought.findByIdAndUpdate( | ||
| thoughtId, | ||
| { | ||
| $inc: { hearts: 1 }, | ||
| }, | ||
| { new: true } | ||
| ).exec(); | ||
| res.status(201).json(post); | ||
| } catch (error) { | ||
| if (error.name === "CastError") { | ||
| error.message = `There's no post matching id:${thoughtId}`; | ||
| } | ||
| res.status(400).json({ | ||
| success: false, | ||
| error: error.message, | ||
| message: "Could not like the thought...", | ||
| }); | ||
| } | ||
| }); | ||
|
|
||
| //unlike a post | ||
| app.post("/thoughts/:thoughtId/unlike", async (req, res) => { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Love this! What do you think about having both the like and dislike in the same endpoint though? Maybe some kind of param differing them, since both are changing the likes? |
||
| const { thoughtId } = req.params; | ||
| // Prevent unlike on posts with hearts below or equal to 0 | ||
| try { | ||
| const post = await Thought.findOneAndUpdate( | ||
| { _id: thoughtId, hearts: { $gte: 1 } }, | ||
| { | ||
| $inc: { hearts: -1 }, | ||
| }, | ||
| { new: true } | ||
| ).exec(); | ||
| if (post) { | ||
| res.status(201).json(post); | ||
| } else { | ||
| throw new Error("The post's like is 0 hence cannot be unliked"); | ||
| } | ||
| } catch (error) { | ||
| if (error.name === "CastError") { | ||
| error.message = `There's no post matching id:${thoughtId}`; | ||
| } | ||
| res.status(400).json({ | ||
| success: false, | ||
| error: error.message, | ||
| message: "Could not unlike the thought...", | ||
| }); | ||
| } | ||
| }); | ||
|
|
||
| // Start the server | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea breaking this out!