mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-29 05:29:02 +00:00
Pass shareKey as context while fetching space (#2409)
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
]);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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": {
|
||||
|
||||
Reference in New Issue
Block a user