Skip to content

Commit

Permalink
Merge branch 'main' into scottcazan/rnd-5393-track-page-view-with-sit…
Browse files Browse the repository at this point in the history
…espaceid-in-api
  • Loading branch information
scazan authored Nov 15, 2024
2 parents 60ad16c + 7675c2c commit 9ec06b3
Show file tree
Hide file tree
Showing 18 changed files with 139 additions and 348 deletions.
5 changes: 5 additions & 0 deletions .changeset/long-dryers-try.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'gitbook': patch
---

Optimize performances by using new API endpoint for fetching site data.
Binary file modified bun.lockb
Binary file not shown.
2 changes: 1 addition & 1 deletion packages/gitbook/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"clean": "rm -rf ./.next && rm -rf ./public/~gitbook/static"
},
"dependencies": {
"@gitbook/api": "^0.73.0",
"@gitbook/api": "^0.76.0",
"@gitbook/cache-do": "workspace:*",
"@gitbook/emoji-codepoints": "workspace:*",
"@gitbook/icons": "workspace:*",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { getSpaceLanguage, t } from '@/intl/server';
import { getSiteLayoutData } from '@/lib/api';
import { getSiteData } from '@/lib/api';
import { getSiteContentPointer } from '@/lib/pointer';
import { tcls } from '@/lib/tailwind';

export default async function NotFound() {
const pointer = getSiteContentPointer();
const { customization } = await getSiteLayoutData(pointer);
const { customization } = await getSiteData(pointer);

const language = getSpaceLanguage(customization);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export default async function Page(props: {
page,
};

const withSections = Boolean(sections && sections.length > 0);
const withSections = Boolean(sections && sections.list.length > 0);
const headerOffset = { sectionsHeader: withSections, topHeader: withTopHeader };

return (
Expand Down
3 changes: 1 addition & 2 deletions packages/gitbook/src/app/(site)/(core)/robots.txt/route.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ContentVisibility } from '@gitbook/api';
import { NextRequest } from 'next/server';

import { getCollection, getSite, getSpace } from '@/lib/api';
import { getSpace, getSite } from '@/lib/api';
import { absoluteHref } from '@/lib/links';
import { getSiteContentPointer } from '@/lib/pointer';
import { isSpaceIndexable } from '@/lib/seo';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ImageResponse } from 'next/og';
import { NextRequest } from 'next/server';
import React from 'react';

import { getCurrentSiteCustomization, getSite, getSpace } from '@/lib/api';
import { getSite, getSiteData, getSpace } from '@/lib/api';
import { getEmojiForCode } from '@/lib/emojis';
import { getSiteContentPointer } from '@/lib/pointer';
import { tcls } from '@/lib/tailwind';
Expand Down Expand Up @@ -38,9 +38,9 @@ export async function GET(req: NextRequest) {
const pointer = getSiteContentPointer();
const spaceId = pointer.spaceId;

const [space, customization] = await Promise.all([
const [space, { customization }] = await Promise.all([
getSpace(spaceId, pointer.siteShareKey),
getCurrentSiteCustomization(pointer),
getSiteData(pointer),
]);
const site = await getSite(pointer.organizationId, pointer.siteId);
const contentTitle = getContentTitle(space, customization, site);
Expand Down
118 changes: 11 additions & 107 deletions packages/gitbook/src/app/(site)/fetch.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import { RevisionPage, SiteSection, SiteSpace, Space } from '@gitbook/api';
import { assert } from 'ts-essentials';
import { RevisionPage } from '@gitbook/api';

import {
getRevisionPageByPath,
getDocument,
ContentTarget,
getSpaceContentData,
getSiteData,
getSite,
getCurrentSiteCustomization,
getSiteStructure,
} from '@/lib/api';
import { resolvePagePath, resolvePageId } from '@/lib/pages';
import { getSiteContentPointer } from '@/lib/pointer';
Expand All @@ -21,35 +18,18 @@ export interface PageIdParams {
pageId: string;
}

export type SectionsList = { list: SiteSection[]; section: SiteSection; index: number };

/**
* Fetch all the data needed to render the content layout.
*/
export async function fetchContentData() {
const content = getSiteContentPointer();

const [{ space, contentTarget, pages, customization, scripts }, siteStructure] =
const [{ space, contentTarget, pages }, { customization, site, sections, spaces, scripts }] =
await Promise.all([
getSpaceContentData(content, content.siteShareKey),
getSiteData(content),
fetchSiteStructure({
organizationId: content.organizationId,
siteId: content.siteId,
siteShareKey: content.siteShareKey,
}),
]);

const site = siteStructure.site;

const siteSections =
content.siteSectionId && siteStructure.sections
? parseSiteSectionsList(content.siteSectionId, siteStructure.sections)
: null;

const spaces =
siteStructure.spaces ??
(siteSections ? parseSpacesFromSiteSpaces(siteSections.section.siteSpaces) : []);

// we grab the space attached to the parent as it contains overriden customizations
const spaceRelativeToParent = spaces?.find((space) => space.id === content.spaceId);

Expand All @@ -58,53 +38,30 @@ export async function fetchContentData() {
contentTarget,
space: spaceRelativeToParent ?? space,
pages,
sections: siteSections,
site,
sections,
spaces,
customization,
scripts,
ancestors: [],
};
}

function parseSiteSectionsList(siteSectionId: string, sections: SiteSection[]) {
const section = sections.find((section) => section.id === siteSectionId);
assert(sectionIsDefined(section), 'A section must be defined when there are multiple sections');
return { list: sections, section, index: sections.indexOf(section) } satisfies SectionsList;
}

function sectionIsDefined(section?: SiteSection): section is NonNullable<SiteSection> {
return typeof section !== 'undefined' && section !== null;
}

/**
* Fetch all the data needed to render the content.
* Optimized to fetch in parallel as much as possible.
*/
export async function fetchPageData(params: PagePathParams | PageIdParams) {
const content = getSiteContentPointer();
const contentData = await fetchContentData();

const { space, contentTarget, pages, customization, scripts } = await getSiteData(content);
const page = await resolvePage(contentTarget, pages, params);
const [siteStructure, document] = await Promise.all([
fetchSiteStructure({
organizationId: content.organizationId,
siteId: content.siteId,
siteShareKey: content.siteShareKey,
}),
page?.page.documentId ? getDocument(space.id, page.page.documentId) : null,
]);
const page = await resolvePage(contentData.contentTarget, contentData.pages, params);
const document = page?.page.documentId
? await getDocument(contentData.space.id, page.page.documentId)
: null;

return {
content,
contentTarget,
space,
pages,
customization,
scripts,
ancestors: [],
...contentData,
...page,
...siteStructure,
document,
};
}
Expand Down Expand Up @@ -150,59 +107,6 @@ async function resolvePage(
return undefined;
}

/**
* Fetch the structure of an organization site.
* This includes the site and its sections or spaces.
*/
async function fetchSiteStructure(args: {
organizationId: string;
siteId: string;
siteShareKey: string | undefined;
}) {
const { organizationId, siteId, siteShareKey } = args;
const [orgSite, siteStructure, siteParentCustomizations] = await Promise.all([
getSite(organizationId, siteId),
getSiteStructure({ organizationId, siteId, siteShareKey }),
getCurrentSiteCustomization({ organizationId, siteId, siteSpaceId: undefined }),
]);

const siteSections =
siteStructure.type === 'sections' && siteStructure.structure
? siteStructure.structure
: null;
const siteSpaces =
siteStructure.type === 'siteSpaces' && siteStructure.structure
? parseSpacesFromSiteSpaces(siteStructure.structure)
: null;

// override the title with the customization title
const site = {
...orgSite,
...(siteParentCustomizations?.title ? { title: siteParentCustomizations.title } : {}),
};

return {
site,
spaces: siteSpaces,
sections: siteSections,
};
}

function parseSpacesFromSiteSpaces(siteSpaces: SiteSpace[]) {
const spaces: Record<string, Space> = {};
siteSpaces.forEach((siteSpace) => {
spaces[siteSpace.space.id] = {
...siteSpace.space,
title: siteSpace.title ?? siteSpace.space.title,
urls: {
...siteSpace.space.urls,
published: siteSpace.urls.published,
},
};
});
return Object.values(spaces);
}

/**
* Get the page path from the params.
*/
Expand Down
4 changes: 2 additions & 2 deletions packages/gitbook/src/app/(site)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CustomizationRootLayout } from '@/components/RootLayout';
import { getSiteLayoutData } from '@/lib/api';
import { getSiteData } from '@/lib/api';
import { getSiteContentPointer } from '@/lib/pointer';

/**
Expand All @@ -10,7 +10,7 @@ export default async function SiteRootLayout(props: { children: React.ReactNode
const { children } = props;

const pointer = getSiteContentPointer();
const { customization } = await getSiteLayoutData(pointer);
const { customization } = await getSiteData(pointer);

return (
<CustomizationRootLayout customization={customization}>{children}</CustomizationRootLayout>
Expand Down
6 changes: 3 additions & 3 deletions packages/gitbook/src/app/(space)/~gitbook/pdf/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { SpaceIntegrationScript } from '@gitbook/api';

import { CustomizationRootLayout } from '@/components/RootLayout';
import { getSiteLayoutData, getSpaceCustomization } from '@/lib/api';
import { getSiteData, getSpaceCustomization } from '@/lib/api';

import { getSiteOrSpacePointerForPDF } from './pointer';

Expand All @@ -14,7 +14,7 @@ export default async function PDFRootLayout(props: { children: React.ReactNode }

const pointer = getSiteOrSpacePointerForPDF();
const { customization } = await ('siteId' in pointer
? getSiteLayoutData(pointer)
? getSiteData(pointer)
: getSpaceLayoutData(pointer.spaceId));

return (
Expand All @@ -26,7 +26,7 @@ export default async function PDFRootLayout(props: { children: React.ReactNode }
* Fetch all the layout data about a space at once.
*/
async function getSpaceLayoutData(spaceId: string) {
const [customization, scripts] = await Promise.all([
const [{ customization }, scripts] = await Promise.all([
getSpaceCustomization(spaceId),
[] as SpaceIntegrationScript[],
]);
Expand Down
14 changes: 5 additions & 9 deletions packages/gitbook/src/app/(space)/~gitbook/pdf/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
getSpace,
getSpaceCustomization,
getSpaceContentData,
getCurrentSiteCustomization,
getSiteData,
} from '@/lib/api';
import { pagePDFContainerId, PageHrefContext, absoluteHref } from '@/lib/links';
import { resolvePageId } from '@/lib/pages';
Expand All @@ -40,11 +40,9 @@ export const runtime = 'edge';

export async function generateMetadata(): Promise<Metadata> {
const pointer = getSiteOrSpacePointerForPDF();
const [space, customization] = await Promise.all([
const [space, { customization }] = await Promise.all([
getSpace(pointer.spaceId, 'siteId' in pointer ? pointer.siteShareKey : undefined),
'siteId' in pointer
? getCurrentSiteCustomization(pointer)
: getSpaceCustomization(pointer.spaceId),
'siteId' in pointer ? getSiteData(pointer) : getSpaceCustomization(pointer.spaceId),
]);

return {
Expand All @@ -67,10 +65,8 @@ export default async function PDFHTMLOutput(props: { searchParams: { [key: strin
currentPDFUrl += '?' + searchParams.toString();

// Load the content,
const [customization, { space, contentTarget, pages: rootPages }] = await Promise.all([
'siteId' in pointer
? getCurrentSiteCustomization(pointer)
: getSpaceCustomization(pointer.spaceId),
const [{ customization }, { space, contentTarget, pages: rootPages }] = await Promise.all([
'siteId' in pointer ? getSiteData(pointer) : getSpaceCustomization(pointer.spaceId),
getSpaceContentData(pointer, 'siteId' in pointer ? pointer.siteShareKey : undefined),
]);
const language = getSpaceLanguage(customization);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ async function SpaceRefCard(
return null;
}

const spaceCustomization = await ignoreAPIError(getSpaceCustomization(spaceId));
const { customization: spaceCustomization } = getSpaceCustomization(spaceId);
const customFavicon = spaceCustomization?.favicon;
const customEmoji = customFavicon && 'emoji' in customFavicon ? customFavicon.emoji : undefined;
const customIcon = customFavicon && 'icon' in customFavicon ? customFavicon.icon : undefined;
Expand Down
2 changes: 1 addition & 1 deletion packages/gitbook/src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { CustomizationSettings, Site, SiteCustomizationSettings, Space } from '@
import { CustomizationHeaderPreset } from '@gitbook/api';
import { Suspense } from 'react';

import type { SectionsList } from '@/app/(site)/fetch';
import { CONTAINER_STYLE, HEADER_HEIGHT_DESKTOP } from '@/components/layout';
import { t, getSpaceLanguage } from '@/intl/server';
import type { SectionsList } from '@/lib/api';
import { ContentRefContext } from '@/lib/references';
import { tcls } from '@/lib/tailwind';

Expand Down
11 changes: 3 additions & 8 deletions packages/gitbook/src/components/Search/server-actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,11 @@ async function searchSiteContent(args: {
scope.mode === 'current' ||
(scope.mode === 'specific' && scope.siteSpaceIds.length > 1);

const [searchResults, siteStructure] = await Promise.all([
const [searchResults, siteData] = await Promise.all([
api.searchSiteContent(pointer.organizationId, pointer.siteId, query, scope, cacheBust),
needsStructure
? api.getSiteStructure({
organizationId: pointer.organizationId,
siteId: pointer.siteId,
siteShareKey: pointer.siteShareKey,
})
: null,
needsStructure ? api.getSiteData(pointer) : null,
]);
const siteStructure = siteData?.structure;

const siteSpaces = siteStructure
? siteStructure.type === 'siteSpaces'
Expand Down
3 changes: 1 addition & 2 deletions packages/gitbook/src/components/SpaceLayout/SpaceLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,13 @@ import {
} from '@gitbook/api';
import React from 'react';

import { SectionsList } from '@/app/(site)/fetch';
import { Footer } from '@/components/Footer';
import { CompactHeader, Header } from '@/components/Header';
import { CONTAINER_STYLE } from '@/components/layout';
import { ColorDebugger } from '@/components/primitives/ColorDebugger';
import { SearchModal } from '@/components/Search';
import { TableOfContents } from '@/components/TableOfContents';
import { ContentTarget, SiteContentPointer } from '@/lib/api';
import { ContentTarget, type SectionsList, SiteContentPointer } from '@/lib/api';
import { ContentRefContext } from '@/lib/references';
import { tcls } from '@/lib/tailwind';

Expand Down
Loading

0 comments on commit 9ec06b3

Please sign in to comment.