Pass shareKey as context while fetching space (#2409)

This commit is contained in:
Taran Vohra
2024-07-26 16:14:20 +05:30
committed by GitHub
parent 32a73b55d4
commit e9fe3975bb
14 changed files with 78 additions and 34 deletions
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -15,7 +15,7 @@
},
"dependencies": {
"@geist-ui/icons": "^1.0.2",
"@gitbook/api": "^0.56.0",
"@gitbook/api": "^0.58.0",
"@gitbook/react-math": "workspace:*",
"@gitbook/react-openapi": "workspace:*",
"@gitbook/react-contentkit": "workspace:*",
@@ -64,6 +64,7 @@ export default async function Page(props: {
const withPageFeedback = customization.feedback.enabled;
const contentRefContext: ContentRefContext = {
siteContext: 'siteId' in contentPointer ? contentPointer : null,
space,
revisionId: contentTarget.revisionId,
pages,
@@ -14,7 +14,10 @@ export const runtime = 'edge';
*/
export async function GET(req: NextRequest) {
const pointer = getContentPointer();
const space = await getSpace(pointer.spaceId);
const space = await getSpace(
pointer.spaceId,
'siteId' in pointer ? pointer.siteShareKey : undefined,
);
const parent =
'siteId' in pointer
? await getSite(pointer.organizationId, pointer.siteId)
@@ -14,7 +14,11 @@ export const runtime = 'edge';
* Generate a sitemap.xml for the current space.
*/
export async function GET(req: NextRequest) {
const { pages: rootPages } = await getSpaceContentData(getContentPointer());
const pointer = getContentPointer();
const { pages: rootPages } = await getSpaceContentData(
pointer,
'siteId' in pointer ? pointer.siteShareKey : undefined,
);
const pages = flattenPages(rootPages, (page) => !page.hidden);
const urls = pages.map(({ page, depth }) => {
// Decay priority with depth
@@ -46,7 +46,7 @@ export async function GET(req: NextRequest) {
const spaceId = pointer.spaceId;
const [space, customization] = await Promise.all([
getSpace(spaceId),
getSpace(spaceId, 'siteId' in pointer ? pointer.siteShareKey : undefined),
'siteId' in pointer ? getCurrentSiteCustomization(pointer) : getSpaceCustomization(spaceId),
]);
const parent =
@@ -42,7 +42,10 @@ export const runtime = 'edge';
export async function generateMetadata(): Promise<Metadata> {
const contentPointer = getContentPointer();
const [space, customization] = await Promise.all([
getSpace(contentPointer.spaceId),
getSpace(
contentPointer.spaceId,
'siteId' in contentPointer ? contentPointer.siteShareKey : undefined,
),
'siteId' in contentPointer
? getCurrentSiteCustomization(contentPointer)
: getSpaceCustomization(contentPointer.spaceId),
@@ -72,7 +75,10 @@ export default async function PDFHTMLOutput(props: { searchParams: { [key: strin
'siteId' in contentPointer
? getCurrentSiteCustomization(contentPointer)
: getSpaceCustomization(contentPointer.spaceId),
getSpaceContentData(contentPointer),
getSpaceContentData(
contentPointer,
'siteId' in contentPointer ? contentPointer.siteShareKey : undefined,
),
]);
const language = getSpaceLanguage(customization);
@@ -170,6 +176,7 @@ export default async function PDFHTMLOutput(props: { searchParams: { [key: strin
space={space}
page={page}
refContext={{
siteContext: 'siteId' in contentPointer ? contentPointer : null,
space,
revisionId: contentTarget.revisionId,
pages: rootPages,
+6 -3
View File
@@ -71,6 +71,8 @@ export function getContentPointer(): ContentPointer | SiteContentPointer {
export async function fetchSpaceData() {
const content = getContentPointer();
const siteShareKey = 'siteId' in content ? content.siteShareKey : undefined;
const [{ space, contentTarget, pages, customization, scripts }, parentSite] = await Promise.all(
'siteId' in content
? [
@@ -78,10 +80,10 @@ export async function fetchSpaceData() {
fetchParentSite({
organizationId: content.organizationId,
siteId: content.siteId,
siteShareKey: content.siteShareKey,
siteShareKey,
}),
]
: [getSpaceData(content)],
: [getSpaceData(content, siteShareKey)],
);
const parent = await (parentSite ?? fetchParentCollection(space));
@@ -104,9 +106,10 @@ export async function fetchSpaceData() {
*/
export async function fetchPageData(params: PagePathParams | PageIdParams) {
const content = getContentPointer();
const siteShareKey = 'siteId' in content ? content.siteShareKey : undefined;
const { space, contentTarget, pages, customization, scripts } = await ('siteId' in content
? getCurrentSiteData(content)
: getSpaceData(content));
: getSpaceData(content, siteShareKey));
const page = await resolvePage(contentTarget, pages, params);
const [parent, document] = await Promise.all([
@@ -165,7 +165,7 @@ export const streamAskQuestion = streamResponse(async function* (spaceId: string
const stream = api
.api()
.spaces.streamAskInSpace(spaceId, { query, format: 'document', details: true });
const pagesPromise = api.getSpaceContentData({ spaceId });
const pagesPromise = api.getSpaceContentData({ spaceId }, undefined);
for await (const chunk of stream) {
// We run the AI search and fetch the pages in parallel
@@ -17,7 +17,7 @@ import { CONTAINER_STYLE } from '@/components/layout';
import { ColorDebugger } from '@/components/primitives/ColorDebugger';
import { SearchModal } from '@/components/Search';
import { TableOfContents } from '@/components/TableOfContents';
import { ContentPointer, ContentTarget } from '@/lib/api';
import { ContentPointer, ContentTarget, SiteContentPointer } from '@/lib/api';
import { ContentRefContext } from '@/lib/references';
import { tcls } from '@/lib/tailwind';
@@ -25,7 +25,7 @@ import { tcls } from '@/lib/tailwind';
* Render the entire content of the space (header, table of contents, footer, and page content).
*/
export function SpaceLayout(props: {
content: ContentPointer;
content: ContentPointer | SiteContentPointer;
contentTarget: ContentTarget;
space: Space;
parent: Site | Collection | null;
@@ -50,6 +50,7 @@ export function SpaceLayout(props: {
const withTopHeader = customization.header.preset !== CustomizationHeaderPreset.None;
const contentRefContext: ContentRefContext = {
siteContext: 'siteId' in content ? content : null,
space,
revisionId: contentTarget.revisionId,
pages,
+16 -10
View File
@@ -282,11 +282,17 @@ export const getPublishedContentByUrl = cache(
*/
export const getSpace = cache(
'api.getSpace',
async (spaceId: string, options: CacheFunctionOptions) => {
const response = await api().spaces.getSpaceById(spaceId, {
...noCacheFetchOptions,
signal: options.signal,
});
async (spaceId: string, shareKey: string | undefined, options: CacheFunctionOptions) => {
const response = await api().spaces.getSpaceById(
spaceId,
{
shareKey,
},
{
...noCacheFetchOptions,
signal: options.signal,
},
);
return cacheResponse(response, {
revalidateBefore: 60 * 60,
tags: [getAPICacheTag({ tag: 'space', space: spaceId })],
@@ -795,7 +801,7 @@ export const getSiteIntegrationScripts = cache(
*/
export async function getCurrentSiteData(pointer: SiteContentPointer) {
const [{ space, pages, contentTarget }, { customization, scripts }] = await Promise.all([
getSpaceData(pointer),
getSpaceData(pointer, pointer.siteShareKey),
getCurrentSiteLayoutData(pointer),
]);
@@ -940,9 +946,9 @@ export const getCollectionSpaces = cache(
/**
* Fetch all the data to render a space at once.
*/
export async function getSpaceData(pointer: ContentPointer) {
export async function getSpaceData(pointer: ContentPointer, shareKey: string | undefined) {
const [{ space, pages, contentTarget }, { customization, scripts }] = await Promise.all([
getSpaceContentData(pointer),
getSpaceContentData(pointer, shareKey),
getSpaceLayoutData(pointer.spaceId),
]);
@@ -960,9 +966,9 @@ export async function getSpaceData(pointer: ContentPointer) {
* This function executes the requests in parallel and should be used as early as possible
* instead of calling the individual functions.
*/
export async function getSpaceContentData(pointer: ContentPointer) {
export async function getSpaceContentData(pointer: ContentPointer, shareKey: string | undefined) {
const [space, changeRequest] = await Promise.all([
getSpace(pointer.spaceId),
getSpace(pointer.spaceId, shareKey),
pointer.changeRequestId ? getChangeRequest(pointer.spaceId, pointer.changeRequestId) : null,
]);
+21 -5
View File
@@ -3,6 +3,7 @@ import assertNever from 'assert-never';
import {
ContentPointer,
SiteContentPointer,
getCollection,
getDocument,
getRevisionFile,
@@ -36,6 +37,11 @@ export interface ContentRefContext extends PageHrefContext {
*/
baseUrl?: string;
/**
* Site in which we are resolving the content reference.
* If null, the site is not known (legacy published content mode)
*/
siteContext: SiteContentPointer | null;
/**
* Space in which we are resolving the content reference.
*/
@@ -74,7 +80,7 @@ export async function resolveContentRef(
options: ResolveContentRefOptions = {},
): Promise<ResolvedContentRef | null> {
const { resolveAnchorText = false } = options;
const { space, revisionId, pages, page: activePage, ...linksContext } = context;
const { siteContext, space, revisionId, pages, page: activePage, ...linksContext } = context;
switch (contentRef.kind) {
case 'url': {
@@ -102,7 +108,7 @@ export async function resolveContentRef(
case 'anchor':
case 'page': {
if (contentRef.space && contentRef.space !== space.id) {
return resolveContentRefInSpace(contentRef.space, contentRef);
return resolveContentRefInSpace(contentRef.space, siteContext, contentRef);
}
const resolvePageResult =
@@ -175,7 +181,12 @@ export async function resolveContentRef(
const targetSpace =
contentRef.space === space.id
? space
: await ignoreAPIError(getSpace(contentRef.space));
: await ignoreAPIError(
getSpace(
contentRef.space,
siteContext?.siteShareKey ? siteContext.siteShareKey : undefined,
),
);
if (!targetSpace) {
return {
@@ -239,12 +250,16 @@ export async function resolveContentRef(
}
}
async function resolveContentRefInSpace(spaceId: string, contentRef: ContentRef) {
async function resolveContentRefInSpace(
spaceId: string,
siteContext: SiteContentPointer | null,
contentRef: ContentRef,
) {
const pointer: ContentPointer = {
spaceId,
};
const result = await ignoreAPIError(getSpaceContentData(pointer));
const result = await ignoreAPIError(getSpaceContentData(pointer, siteContext?.siteShareKey));
if (!result) {
return null;
}
@@ -258,6 +273,7 @@ async function resolveContentRefInSpace(spaceId: string, contentRef: ContentRef)
}
const resolved = await resolveContentRef(contentRef, {
siteContext,
space,
revisionId: space.revision,
pages,
+9 -6
View File
@@ -172,11 +172,14 @@ export async function middleware(request: NextRequest) {
// Start fetching everything as soon as possible, but do not block the middleware on it
// the cache will handle concurrent calls
await waitUntil(
getSpaceContentData({
spaceId: resolved.space,
changeRequestId: resolved.changeRequest,
revisionId: resolved.revision,
}),
getSpaceContentData(
{
spaceId: resolved.space,
changeRequestId: resolved.changeRequest,
revisionId: resolved.revision,
},
'site' in resolved ? resolved.shareKey : undefined,
),
);
const { scripts } = await ('site' in resolved
@@ -462,7 +465,7 @@ async function lookupSpaceInMultiIdMode(request: NextRequest, url: URL): Promise
authToken: apiToken,
userAgent: userAgent(),
}),
() => getSpace.revalidate(spaceId),
() => getSpace.revalidate(spaceId, undefined),
);
const cookies: LookupCookies = {
+1 -1
View File
@@ -10,7 +10,7 @@
},
"dependencies": {
"classnames": "^2.5.1",
"@gitbook/api": "^0.51.0",
"@gitbook/api": "^0.58.0",
"assert-never": "^1.2.1"
},
"peerDependencies": {