Skip to content
2 changes: 1 addition & 1 deletion apps/api/.env
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
ACCESS_TOKEN_SECRET=[YOUR_ACCESS_TOKEN_SECRET_HERE]
REFRESH_TOKEN_SECRET=[YOUR_REFRESH_TOKEN_SECRET_HERE]
MONGO_URL=[YOUR_MONGO_CONNECTION_STRING_HERE]
MONGO_URL=[YOUR_MONGO_CONNECTION_STRING_HERE]
103 changes: 103 additions & 0 deletions apps/api/src/controllers/post.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { RequestHandler } from 'express';
import Post from '../models/posts';
import Comment from '../models/comment';

// Get all posts
const getAllPosts: RequestHandler = async (req, res) => {
// Return all the posts with a 200 status code
try {
const posts = await Post.find();
return res.status(200).json(posts);
} catch (error) {
const { message } = error;
return res.status(500).json({ message });
}
};

// Get post by category
const getPostByCategory: RequestHandler = async (req, res) => {
const { categoryId } = req.params;
try {
const posts = await Post.find({ category: categoryId });
return res.status(200).json(posts);
} catch (error) {
const { message } = error;
return res.status(500).json({ message });
}
};

// Get post by id
const getPostById: RequestHandler = async (req, res) => {
const { id } = req.params;
try {
const post = await Post.findById(id);
return res.status(200).json(post);
} catch (error) {
const { message } = error;
return res.status(500).json({ message });
}
};

// Create post
const createPost: RequestHandler = async (req, res) => {
const postData = req.body;
try {
const newPost = await Post.create(postData);
return res.status(201).json(newPost);
} catch (error) {
const { message } = error;
return res.status(500).json({ message });
}
};

// Create comments
const createComments: RequestHandler = async (req, res) => {
const { id } = req.params;
const commentData = req.body;
try {
const post = await Post.findById(id);
const comment = await Comment.create(commentData);
post.comments.push(comment._id);
await post.save();
return res.status(201).json(comment);
} catch (error) {
const { message } = error;
return res.status(500).json({ message });
}
};

// Update posts by id
const updatePostById: RequestHandler = async (req, res) => {
const { id } = req.params;
const newPostData = req.body;
try {
const modifiedPost = await Post.findByIdAndUpdate(id, newPostData, { new: true, runValidators: true });
return res.status(200).json(modifiedPost);
} catch (error) {
const { message } = error;
return res.status(500).json({ message });
}
};

// Delete post by id
const deletePost: RequestHandler = async (req, res) => {
const { id } = req.params;
try {
const deletedPost = await Post.findByIdAndDelete(id, {});
await Comment.deleteMany({ _id: { $in: deletedPost.comments } });
return res.status(200).json(deletedPost);
} catch (error) {
const { message } = error;
return res.status(500).json({ message });
}
};

export default {
getAllPosts,
getPostByCategory,
getPostById,
createPost,
createComments,
updatePostById,
deletePost
};
2 changes: 2 additions & 0 deletions apps/api/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { verifyToken } from './middleware/auth';
import { errorHandler } from './middleware/errorHandler';
import auth from './routes/auth';
import categories from './routes/categories';
import posts from './routes/posts';

const host = process.env.HOST ?? 'localhost';
const port = process.env.PORT ? Number(process.env.PORT) : 3000;
Expand All @@ -22,6 +23,7 @@ app.use('/api/auth', auth);

app.use(verifyToken);
app.use('/api/categories', categories);
app.use('/api/posts', posts);

app.use(errorHandler);

Expand Down
26 changes: 26 additions & 0 deletions apps/api/src/models/comment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import mongoose, { Document, Schema } from 'mongoose';

interface IComment extends Document {
author: string;
content: string;
}

export const commentSchema = new Schema<IComment>(
{
author: {
type: String,
required: [true, 'Author is required']
},
content: {
type: String,
required: [true, 'Content is missing']
}
},
{
timestamps: true
}
);

const Comment = mongoose.model<IComment>('Comment', commentSchema);

export default Comment;
44 changes: 44 additions & 0 deletions apps/api/src/models/posts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import mongoose, { Document, Schema } from 'mongoose';

interface IPost extends Document {
title: string;
image: string;
description: string;
category: string;
comments: string[];
}

export const postSchema = new Schema<IPost>(
{
title: {
type: String,
required: [true, 'Title is required'],
maxlength: [256, 'title should be no greater than 256 characters']
},
image: {
type: String,
required: [true, 'image URL is missing']
},
description: {
type: String,
required: [true, 'Description is required']
},
category: {
type: String,
required: [true, 'Category Id is missing']
},
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Comment'
}
]
},
{
timestamps: true
}
);

const Post = mongoose.model<IPost>('Post', postSchema);

export default Post;
28 changes: 28 additions & 0 deletions apps/api/src/routes/posts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import express from 'express';

import postController from '../controllers/post';

const router = express.Router();

// Get all posts
router.get('/', postController.getAllPosts);

// Get post by category
router.get('/category/:category', postController.getPostByCategory);

// Get post by id
router.get('/:id', postController.getPostById);

// Create post
router.post('/', postController.createPost);

// Create comments
router.post('/:id/comments', postController.createComments);

// Update posts by id
router.patch('/:id', postController.updatePostById);

// Delete post by id
router.delete('/:id', postController.deletePost);

export default router;