1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
import { Comment } from '@ts/types/app';
import { GraphQLEdgesInput } from '@ts/types/graphql/generics';
import { SendCommentInput, SentComment } from '@ts/types/graphql/mutations';
import { ContentId } from '@ts/types/graphql/queries';
import { RawComment } from '@ts/types/raw-data';
import { getAuthorFromRawData } from '@utils/helpers/author';
import { fetchAPI } from './api';
import { sendCommentMutation } from './comments.mutation';
import { commentsQuery } from './comments.query';
type FetchCommentsInput = ContentId &
Pick<GraphQLEdgesInput, 'after' | 'first'>;
/**
* Retrieve the comments list from GraphQL.
*
* @param {FetchCommentsInput} variables - An object of variables.
* @returns {Promise<RawComment[]>} The raw comments.
*/
export const fetchComments = async (
variables: FetchCommentsInput
): Promise<RawComment[]> => {
const response = await fetchAPI<RawComment, typeof commentsQuery>({
query: commentsQuery,
variables,
});
return response.comments.nodes;
};
/**
* Create a comments tree with replies.
*
* @param {Comment[]} comments - A flatten comments list.
* @returns {Comment[]} An array of comments with replies.
*/
export const buildCommentsTree = (comments: Comment[]): Comment[] => {
type CommentsHashTable = {
[key: string]: Comment;
};
const hashTable: CommentsHashTable = Object.create(null);
const commentsTree: Comment[] = [];
comments.forEach(
(comment) => (hashTable[comment.id] = { ...comment, replies: [] })
);
comments.forEach((comment) => {
if (!comment.parentId) {
commentsTree.push(hashTable[comment.id]);
} else {
hashTable[comment.parentId].replies.push(hashTable[comment.id]);
}
});
return commentsTree;
};
/**
* Convert a comment from RawComment to Comment type.
*
* @param {RawComment} comment - A raw comment.
* @returns {Comment} A formatted comment.
*/
export const getCommentFromRawData = (comment: RawComment): Comment => {
const { author, databaseId, date, parentDatabaseId, ...data } = comment;
return {
id: databaseId,
meta: {
author: getAuthorFromRawData(author.node, 'comment'),
date,
},
parentId: parentDatabaseId,
replies: [],
...data,
};
};
/**
* Retrieve a comments list by post id.
*
* @param {number} id - A post id.
* @returns {Promise<Comment[]>} The comments list.
*/
export const getPostComments = async (id: number): Promise<Comment[]> => {
const rawComments = await fetchComments({ contentId: id });
const comments = rawComments.map((comment) => getCommentFromRawData(comment));
return buildCommentsTree(comments);
};
/**
* Send a comment using GraphQL API.
*
* @param {SendCommentVars} data - The comment data.
* @returns {Promise<SentEmail>} The mutation response.
*/
export const sendComment = async (
data: SendCommentInput
): Promise<SentComment> => {
const response = await fetchAPI<SentComment, typeof sendCommentMutation>({
query: sendCommentMutation,
variables: { ...data },
});
return response.createComment;
};
|