summaryrefslogtreecommitdiffstats
path: root/src/services/graphql/articles.ts
blob: e5ce7a57b741ac0583200975cee8f1b2f1b30619 (plain)
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
import { Article } from '@ts/types/app';
import { RawArticle, TotalItems } from '@ts/types/raw-data';
import { getAuthorFromRawData } from '@utils/helpers/author';
import { getImageFromRawData } from '@utils/helpers/images';
import { getPageLinkFromRawData } from '@utils/helpers/pages';
import { EdgesVars, fetchAPI, getAPIUrl, PageInfo } from './api';
import { articlesQuery, totalArticlesQuery } from './articles.query';

/**
 * Retrieve the total number of articles.
 *
 * @returns {Promise<number>} - The articles total number.
 */
export const getTotalArticles = async (): Promise<number> => {
  const response = await fetchAPI<TotalItems, typeof totalArticlesQuery>({
    api: getAPIUrl(),
    query: totalArticlesQuery,
  });

  return response.posts.pageInfo.total;
};

export type GetArticlesReturn = {
  articles: Article[];
  pageInfo: PageInfo;
};

/**
 * Convert raw data to an Article object.
 *
 * @param {RawArticle} data - The page raw data.
 * @returns {Article} The page data.
 */
export const getArticleFromRawData = (data: RawArticle): Article => {
  const {
    acfPosts,
    author,
    commentCount,
    contentParts,
    databaseId,
    date,
    featuredImage,
    info,
    modified,
    slug,
    title,
    seo,
  } = data;

  return {
    content: contentParts.afterMore,
    id: databaseId,
    intro: contentParts.beforeMore,
    meta: {
      author: getAuthorFromRawData(author.node, 'page'),
      commentsCount: commentCount || 0,
      cover: featuredImage?.node
        ? getImageFromRawData(featuredImage.node)
        : undefined,
      dates: {
        publication: date,
        update: modified,
      },
      readingTime: info.readingTime,
      seo: {
        description: seo?.metaDesc || '',
        title: seo?.title || '',
      },
      thematics: acfPosts.postsInThematic?.map((thematic) =>
        getPageLinkFromRawData(thematic)
      ),
      topics: acfPosts.postsInTopic?.map((topic) =>
        getPageLinkFromRawData(topic)
      ),
      wordsCount: info.wordsCount,
    },
    slug,
    title,
  };
};

/**
 * Retrieve the given number of articles from API.
 *
 * @param {EdgesVars} obj - An object.
 * @param {number} obj.first - The number of articles.
 * @returns {Promise<GetArticlesReturn>} - The articles data.
 */
export const getArticles = async ({
  first,
}: EdgesVars): Promise<GetArticlesReturn> => {
  const response = await fetchAPI<RawArticle, typeof articlesQuery>({
    api: getAPIUrl(),
    query: articlesQuery,
    variables: { first },
  });

  return {
    articles: response.posts.edges.map((edge) =>
      getArticleFromRawData(edge.node)
    ),
    pageInfo: response.posts.pageInfo,
  };
};