shack/src/comments.js

84 lines
1.9 KiB
JavaScript

import knex from './knex';
import { fetchUsers } from './users';
import { verifyPrivilege } from './privileges';
import { HttpError } from './errors';
function curateDatabaseComment(comment, { users }) {
return {
id: comment.id,
body: comment.body,
parentId: comment.parent_id,
userId: comment.user_id,
user: users.find((user) => user.id === comment.user_id),
createdAt: comment.created_at,
};
}
function threadComments(thread, commentsByParentId) {
if (!thread) {
return [];
}
return thread.map((comment) => ({
...comment,
comments: threadComments(commentsByParentId[comment.id], commentsByParentId),
}));
}
function nestComments(comments) {
const commentsByParentId = comments.reduce((acc, comment) => {
if (!acc[comment.parentId]) {
acc[comment.parentId] = [];
}
acc[comment.parentId].push(comment);
return acc;
}, {});
return threadComments(commentsByParentId.null, commentsByParentId);
}
async function fetchPostComments(postId, { limit = 100 } = {}) {
const comments = await knex('comments')
.where('post_id', postId)
.orderBy('created_at', 'desc')
.limit(limit);
const users = await fetchUsers(comments.map((comment) => comment.user_id));
const curatedComments = comments.map((comment) => curateDatabaseComment(comment, { users }));
const nestedComments = nestComments(curatedComments);
return nestedComments;
}
async function addComment(comment, postId, user) {
await verifyPrivilege('addComment', user);
if (!comment.body) {
throw new HttpError({
statusMessage: 'Comment cannot be empty',
statusCode: 400,
});
}
const [commentEntry] = await knex('comments')
.insert({
body: comment.body,
post_id: postId,
parent_id: comment.parentId,
user_id: user.id,
})
.returning('*');
const users = await fetchUsers([commentEntry.user_id]);
return curateDatabaseComment(commentEntry, { users });
}
export {
fetchPostComments,
addComment,
};