import { GatsbyNode } from "gatsby"; import * as constants from "./constants"; import * as queries from "./queries"; import * as utils from "./utils"; type CreateWithPagination = (parameters: { limit: number; group?: string; template: string; total: number; page: number; path: string; }) => void; const getPaginationPath = (basePath: string, page: number): string => [basePath === "/" ? "" : basePath, "page", page].join("/"); const createPages: GatsbyNode["createPages"] = async ({ graphql, actions }) => { const { createPage } = actions; createPage({ path: constants.routes.notFoundRoute, component: constants.templates.notFoundTemplate, context: {}, }); createPage({ path: constants.routes.tagsListRoute, component: constants.templates.tagsTemplate, context: {}, }); createPage({ path: constants.routes.categoriesListRoute, component: constants.templates.categoriesTemplate, context: {}, }); const pages = await queries.pagesQuery(graphql); const { pageTemplate, postTemplate } = constants.templates; pages.forEach((edge) => { const { node } = edge; if (node?.fields?.slug) { switch (node?.frontmatter?.template) { case "page": createPage({ path: node.fields.slug, component: pageTemplate, context: { slug: node.fields.slug }, }); break; case "post": createPage({ path: node.fields.slug, component: postTemplate, context: { slug: node.fields.slug, readingTime: node?.fields?.readingTime }, }); break; } } }); const createWithPagination: CreateWithPagination = ({ group, template, page, path, total, limit, }) => { createPage({ component: template, path: page === 0 ? path : getPaginationPath(path, page), context: { group, limit, offset: page * limit, pagination: { currentPage: page, prevPagePath: page <= 1 ? path : getPaginationPath(path, utils.decrement(page)), nextPagePath: getPaginationPath(path, utils.increment(page)), hasNextPage: page !== utils.decrement(total), hasPrevPage: page !== 0, }, }, }); }; const categories = await queries.categoriesQuery(graphql); const metadata = await queries.metadataQuery(graphql); const postsLimit = metadata?.postsLimit ?? 1; categories.forEach((category) => { const total = Math.ceil(category.totalCount / postsLimit); const path = utils.concat( constants.routes.categoryRoute, "/", utils.toKebabCase(category.fieldValue) ); for (let page = 0; page < total; page += 1) { createWithPagination({ limit: postsLimit, group: category.fieldValue, template: constants.templates.categoryTemplate, total, page, path, }); } }); const tags = await queries.tagsQuery(graphql); tags.forEach((tag) => { const path = utils.concat(constants.routes.tagRoute, "/", utils.toKebabCase(tag.fieldValue)); const total = Math.ceil(tag.totalCount / postsLimit); for (let page = 0; page < total; page += 1) { createWithPagination({ limit: postsLimit, group: tag.fieldValue, template: constants.templates.tagTemplate, total, page, path, }); } }); const path = constants.routes.indexRoute; const template = constants.templates.indexTemplate; const posts = await queries.postsQuery(graphql); const total = Math.ceil((posts?.edges?.length ?? 0) / postsLimit); for (let page = 0; page < total; page += 1) { createWithPagination({ limit: postsLimit, template, total, page, path, }); } }; export { createPages };