William Nemenchainitial commit
86fb32e9/11/2022, 1:13:39 AM
.ts
TypeScript
(application/typescript)
// 1st-party
import { HeadTag } from "@ethicdevs/fastify-stream-react-views";
import { ReqHandler } from "@ethicdevs/react-monolith";
// app
import type { Page, SectionsWithPages } from "../types";
import { Const } from "../const";
import { Env } from "../env";
import { getDocFileContent } from "../utils/server";
import { makeSectionsService } from "../services/SectionsService";

import DocHomeView, { DocHomeViewProps } from "../views/DocHomeView";
import DocPageView, { DocPageViewProps } from "../views/DocPageView";

export const getDocHomeView: ReqHandler = async (request, reply) => {
  const reqHandler = reply.makeRequestHandler(request, reply);
  return reqHandler<DocHomeViewProps>(DocHomeView.name, {
    title: "Documentation",
  });
};

export const reloadDocsEndpoint: ReqHandler = async (request, reply) => {
  // Reload content data in memory
  const sectionsWithPages: SectionsWithPages = await Object.entries(
    Const.SECTIONS_WITH_PAGES
  ).reduce(async (accP, [sectionSlug, sectionPagesSlugs]) => {
    let acc = await accP;
    const pageForSection = await sectionPagesSlugs.reduce(
      async (accP, pageSlug) => {
        const acc = await accP;
        const page = await getDocFileContent(sectionSlug, pageSlug, "md");
        return {
          ...acc,
          [pageSlug]: page,
        };
      },
      Promise.resolve({} as { [pageSlug: string]: Page })
    );
    acc = {
      ...acc,
      [sectionSlug]: {
        slug: sectionSlug,
        title: Const.SECTIONS_TITLES[sectionSlug],
        summary: Const.SECTIONS_SUMMARIES[sectionSlug],
        pagesBySlug: pageForSection,
      },
    };
    return acc;
  }, Promise.resolve({} as SectionsWithPages));

  // (for the setter definition @see server.ts)
  request.sectionsWithPages = sectionsWithPages;

  return reply.send("OK");
};

export const getSectionEntrypoint: ReqHandler = async (request, reply) => {
  const { sectionSlug } = request.params as { sectionSlug: string };

  const sectionsService = await makeSectionsService(request);
  const section = await sectionsService.getSectionBySlug(sectionSlug);
  const firstPage = await sectionsService.getFirstPage(section);

  if (firstPage == null) {
    return reply.redirect(302, `/docs`);
  }

  return reply.redirect(302, `/docs/${section.slug}/${firstPage.slug}`);
};

export const getSectionPageView: ReqHandler = async (request, reply) => {
  const { sectionSlug, pageSlug } = request.params as {
    sectionSlug: string;
    pageSlug: string;
  };

  if (pageSlug == null || pageSlug.trim() === "") {
    return reply.redirect(307, `/docs/${sectionSlug}`);
  }

  const sectionsService = await makeSectionsService(request);
  const section = await sectionsService.getSectionBySlug(sectionSlug);

  if (
    section == null ||
    pageSlug in section.pagesBySlug === false ||
    section.pagesBySlug[pageSlug] == null
  ) {
    return reply.callNotFound();
  }

  const page = section.pagesBySlug[pageSlug];

  const reqHandler = reply.makeRequestHandler(request, reply);
  return reqHandler<DocPageViewProps>(
    DocPageView.name,
    {
      page,
      title: `${page.metas?.title} / ${section.title}`,
    },
    {
      head: [
        page.metas?.title && {
          kind: "meta",
          name: "title",
          content: page.metas?.title,
        },
        page.metas?.summary && {
          kind: "meta",
          name: "description",
          content: page.metas?.summary,
        },
        {
          kind: "meta",
          name: "og:type",
          content: "article",
        },
        {
          kind: "meta",
          name: "og:url",
          content: `${Env.DEPLOYMENT_SCHEME}://${Env.DEPLOYMENT_DOMAIN}/docs/${section.slug}/${page.slug}`,
        },
        {
          kind: "meta",
          name: "article:section",
          content: section.title,
        },
        page.metas?.title && {
          kind: "meta",
          name: "og:title",
          content: page.metas?.title,
        },
        page.metas?.summary && {
          kind: "meta",
          name: "og:description",
          content: page.metas?.summary,
        },
      ] as HeadTag[],
    }
  );
};