mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-20 17:43:24 +00:00
Proper data cache tagging for computed content (#2915)
This commit is contained in:
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
'gitbook-v2': patch
|
||||||
|
'gitbook': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Improving data cache management for computed content
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'@gitbook/cache-tags': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Initial version of the package
|
||||||
@@ -22,6 +22,17 @@
|
|||||||
"wrangler": "^3.109.2",
|
"wrangler": "^3.109.2",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"packages/cache-tags": {
|
||||||
|
"name": "@gitbook/cache-tags",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@gitbook/api": "0.96.1",
|
||||||
|
"assert-never": "^1.2.1",
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^5.5.3",
|
||||||
|
},
|
||||||
|
},
|
||||||
"packages/colors": {
|
"packages/colors": {
|
||||||
"name": "@gitbook/colors",
|
"name": "@gitbook/colors",
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
@@ -42,6 +53,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@gitbook/api": "0.96.1",
|
"@gitbook/api": "0.96.1",
|
||||||
"@gitbook/cache-do": "workspace:*",
|
"@gitbook/cache-do": "workspace:*",
|
||||||
|
"@gitbook/cache-tags": "workspace:*",
|
||||||
"@gitbook/colors": "workspace:*",
|
"@gitbook/colors": "workspace:*",
|
||||||
"@gitbook/emoji-codepoints": "workspace:*",
|
"@gitbook/emoji-codepoints": "workspace:*",
|
||||||
"@gitbook/icons": "workspace:*",
|
"@gitbook/icons": "workspace:*",
|
||||||
@@ -122,6 +134,7 @@
|
|||||||
"version": "0.1.1",
|
"version": "0.1.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@gitbook/api": "0.96.1",
|
"@gitbook/api": "0.96.1",
|
||||||
|
"@gitbook/cache-tags": "workspace:*",
|
||||||
"@sindresorhus/fnv1a": "^3.1.0",
|
"@sindresorhus/fnv1a": "^3.1.0",
|
||||||
"next": "^15.2.0",
|
"next": "^15.2.0",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
@@ -618,6 +631,8 @@
|
|||||||
|
|
||||||
"@gitbook/cache-do": ["@gitbook/cache-do@workspace:packages/cache-do"],
|
"@gitbook/cache-do": ["@gitbook/cache-do@workspace:packages/cache-do"],
|
||||||
|
|
||||||
|
"@gitbook/cache-tags": ["@gitbook/cache-tags@workspace:packages/cache-tags"],
|
||||||
|
|
||||||
"@gitbook/colors": ["@gitbook/colors@workspace:packages/colors"],
|
"@gitbook/colors": ["@gitbook/colors@workspace:packages/colors"],
|
||||||
|
|
||||||
"@gitbook/emoji-codepoints": ["@gitbook/emoji-codepoints@workspace:packages/emoji-codepoints"],
|
"@gitbook/emoji-codepoints": ["@gitbook/emoji-codepoints@workspace:packages/emoji-codepoints"],
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
dist/
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# `@gitbook/cache-tags`
|
||||||
|
|
||||||
|
Utility to generate cache tags for GitBook Open.
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"name": "@gitbook/cache-tags",
|
||||||
|
"type": "module",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": "./dist/index.d.ts",
|
||||||
|
"development": "./src/index.ts",
|
||||||
|
"default": "./dist/index.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"version": "0.0.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@gitbook/api": "0.96.1",
|
||||||
|
"assert-never": "^1.2.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^5.5.3"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsc",
|
||||||
|
"typecheck": "tsc --noEmit",
|
||||||
|
"dev": "tsc -w"
|
||||||
|
},
|
||||||
|
"files": ["dist", "src", "README.md", "CHANGELOG.md"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,175 @@
|
|||||||
|
import type { ComputedContentSource } from '@gitbook/api';
|
||||||
|
import assertNever from 'assert-never';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a stringified cache tag for a given object.
|
||||||
|
*/
|
||||||
|
export function getCacheTag(
|
||||||
|
spec: /**
|
||||||
|
* All data related to a user
|
||||||
|
* @deprecated - in v2, no tag as this is an immutable data
|
||||||
|
*/
|
||||||
|
| {
|
||||||
|
tag: 'user';
|
||||||
|
user: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* All data related to a space
|
||||||
|
*/
|
||||||
|
| {
|
||||||
|
tag: 'space';
|
||||||
|
space: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* All data related to an integration.
|
||||||
|
*/
|
||||||
|
| {
|
||||||
|
tag: 'integration';
|
||||||
|
integration: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* All data related to a change request
|
||||||
|
*/
|
||||||
|
| {
|
||||||
|
tag: 'change-request';
|
||||||
|
space: string;
|
||||||
|
changeRequest: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Immutable data related to a revision
|
||||||
|
* @deprecated - in v2, no tag as this is an immutable data
|
||||||
|
*/
|
||||||
|
| {
|
||||||
|
tag: 'revision';
|
||||||
|
space: string;
|
||||||
|
revision: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Immutable data related to a document
|
||||||
|
* @deprecated - in v2, no tag as this is an immutable data
|
||||||
|
*/
|
||||||
|
| {
|
||||||
|
tag: 'document';
|
||||||
|
space: string;
|
||||||
|
document: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Immutable data related to a computed document
|
||||||
|
* @deprecated - in v2, no tag as this is an immutable data
|
||||||
|
*/
|
||||||
|
| {
|
||||||
|
tag: 'computed-document';
|
||||||
|
space: string;
|
||||||
|
integration: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* All data related to the URL of a content
|
||||||
|
*/
|
||||||
|
| {
|
||||||
|
tag: 'url';
|
||||||
|
hostname: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* All data related to a site
|
||||||
|
*/
|
||||||
|
| {
|
||||||
|
tag: 'site';
|
||||||
|
site: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* All data related to an OpenAPI spec
|
||||||
|
*/
|
||||||
|
| {
|
||||||
|
tag: 'openapi';
|
||||||
|
organization: string;
|
||||||
|
openAPISpec: string;
|
||||||
|
}
|
||||||
|
): string {
|
||||||
|
switch (spec.tag) {
|
||||||
|
case 'user':
|
||||||
|
return `user:${spec.user}`;
|
||||||
|
case 'url':
|
||||||
|
return `url:${spec.hostname}`;
|
||||||
|
case 'space':
|
||||||
|
return `space:${spec.space}`;
|
||||||
|
case 'change-request':
|
||||||
|
return `space:${spec.space}:change-request:${spec.changeRequest}`;
|
||||||
|
case 'revision':
|
||||||
|
return `space:${spec.space}:revision:${spec.revision}`;
|
||||||
|
case 'document':
|
||||||
|
return `space:${spec.space}:document:${spec.document}`;
|
||||||
|
case 'computed-document':
|
||||||
|
return `space:${spec.space}:computed-document:${spec.integration}`;
|
||||||
|
case 'site':
|
||||||
|
return `site:${spec.site}`;
|
||||||
|
case 'integration':
|
||||||
|
return `integration:${spec.integration}`;
|
||||||
|
case 'openapi':
|
||||||
|
return `organization:${spec.organization}:openapi:${spec.openAPISpec}`;
|
||||||
|
default:
|
||||||
|
assertNever(spec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the tags for a computed content source.
|
||||||
|
*/
|
||||||
|
export function getComputedContentSourceCacheTags(
|
||||||
|
inContext: {
|
||||||
|
spaceId: string;
|
||||||
|
organizationId: string;
|
||||||
|
},
|
||||||
|
source: ComputedContentSource
|
||||||
|
) {
|
||||||
|
const tags: string[] = [];
|
||||||
|
|
||||||
|
// We add the dependencies as tags, to ensure that the computed content is invalidated
|
||||||
|
// when the dependencies are updated.
|
||||||
|
const dependencies = Object.values(source.dependencies ?? {});
|
||||||
|
if (dependencies.length > 0) {
|
||||||
|
dependencies.forEach((dependency) => {
|
||||||
|
switch (dependency.ref.kind) {
|
||||||
|
case 'space':
|
||||||
|
tags.push(
|
||||||
|
getCacheTag({
|
||||||
|
tag: 'space',
|
||||||
|
space: dependency.ref.space,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'openapi':
|
||||||
|
tags.push(
|
||||||
|
getCacheTag({
|
||||||
|
tag: 'openapi',
|
||||||
|
organization: inContext.organizationId,
|
||||||
|
openAPISpec: dependency.ref.spec,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Do not throw for unknown dependency types
|
||||||
|
// as it might mean we are lacking behind the API version
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Push a dummy tag, as the v1 is only using the first tag
|
||||||
|
tags.push(
|
||||||
|
getCacheTag({
|
||||||
|
tag: 'computed-document',
|
||||||
|
space: inContext.spaceId,
|
||||||
|
integration: source.integration,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We invalidate the computed content when a new version of the integration is deployed.
|
||||||
|
tags.push(
|
||||||
|
getCacheTag({
|
||||||
|
tag: 'integration',
|
||||||
|
integration: source.integration,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "esnext",
|
||||||
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"noEmit": false,
|
||||||
|
"declaration": true,
|
||||||
|
"outDir": "dist",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"incremental": true,
|
||||||
|
"types": [
|
||||||
|
"bun-types" // add Bun global
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"include": ["src/**/*.ts", "src/**/*.tsx"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"@gitbook/api": "0.96.1",
|
"@gitbook/api": "0.96.1",
|
||||||
|
"@gitbook/cache-tags": "workspace:*",
|
||||||
"@sindresorhus/fnv1a": "^3.1.0",
|
"@sindresorhus/fnv1a": "^3.1.0",
|
||||||
"server-only": "^0.0.1"
|
"server-only": "^0.0.1"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import {
|
|||||||
generateSitePageMetadata,
|
generateSitePageMetadata,
|
||||||
generateSitePageViewport,
|
generateSitePageViewport,
|
||||||
} from '@/components/SitePage';
|
} from '@/components/SitePage';
|
||||||
|
import { getCacheTag } from '@gitbook/cache-tags';
|
||||||
import { type RouteParams, getPagePathFromParams, getStaticSiteContext } from '@v2/app/utils';
|
import { type RouteParams, getPagePathFromParams, getStaticSiteContext } from '@v2/app/utils';
|
||||||
import { getSiteCacheTag } from '@v2/lib/cache';
|
|
||||||
import type { Metadata, Viewport } from 'next';
|
import type { Metadata, Viewport } from 'next';
|
||||||
import { unstable_cacheTag as cacheTag } from 'next/cache';
|
import { unstable_cacheTag as cacheTag } from 'next/cache';
|
||||||
|
|
||||||
@@ -21,7 +21,12 @@ export default async function Page(props: PageProps) {
|
|||||||
const context = await getStaticSiteContext(params);
|
const context = await getStaticSiteContext(params);
|
||||||
const pathname = getPagePathFromParams(params);
|
const pathname = getPagePathFromParams(params);
|
||||||
|
|
||||||
cacheTag(getSiteCacheTag(context.site.id));
|
cacheTag(
|
||||||
|
getCacheTag({
|
||||||
|
tag: 'site',
|
||||||
|
site: context.site.id,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
return <SitePage context={context} pageParams={{ pathname }} redirectOnFallback={true} />;
|
return <SitePage context={context} pageParams={{ pathname }} redirectOnFallback={true} />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import {
|
|||||||
generateSiteLayoutMetadata,
|
generateSiteLayoutMetadata,
|
||||||
generateSiteLayoutViewport,
|
generateSiteLayoutViewport,
|
||||||
} from '@/components/SiteLayout';
|
} from '@/components/SiteLayout';
|
||||||
|
import { getCacheTag } from '@gitbook/cache-tags';
|
||||||
import { type RouteLayoutParams, getStaticSiteContext } from '@v2/app/utils';
|
import { type RouteLayoutParams, getStaticSiteContext } from '@v2/app/utils';
|
||||||
import { getSiteCacheTag } from '@v2/lib/cache';
|
|
||||||
import { GITBOOK_DISABLE_TRACKING } from '@v2/lib/env';
|
import { GITBOOK_DISABLE_TRACKING } from '@v2/lib/env';
|
||||||
import { unstable_cacheTag as cacheTag } from 'next/cache';
|
import { unstable_cacheTag as cacheTag } from 'next/cache';
|
||||||
|
|
||||||
@@ -21,7 +21,12 @@ export default async function SiteStaticLayout({
|
|||||||
|
|
||||||
const context = await getStaticSiteContext(await params);
|
const context = await getStaticSiteContext(await params);
|
||||||
|
|
||||||
cacheTag(getSiteCacheTag(context.site.id));
|
cacheTag(
|
||||||
|
getCacheTag({
|
||||||
|
tag: 'site',
|
||||||
|
site: context.site.id,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomizationRootLayout customization={context.customization}>
|
<CustomizationRootLayout customization={context.customization}>
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
/**
|
|
||||||
* Get the cache tag for a site.
|
|
||||||
*/
|
|
||||||
export function getSiteCacheTag(siteId: string) {
|
|
||||||
return `site:${siteId}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the cache tag for a hostname.
|
|
||||||
*/
|
|
||||||
export function getHostnameCacheTag(hostname: string) {
|
|
||||||
return `url:${hostname}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the cache tag for an OpenAPI spec.
|
|
||||||
*/
|
|
||||||
export function getOpenAPISpecCacheTag(organizationId: string, slug: string) {
|
|
||||||
return `organization:${organizationId}:openapi:${slug}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the cache tag for a space.
|
|
||||||
*/
|
|
||||||
export function getSpaceCacheTag(spaceId: string) {
|
|
||||||
return `space:${spaceId}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the cache tag for a change request.
|
|
||||||
*/
|
|
||||||
export function getChangeRequestCacheTag(spaceId: string, changeRequestId: string) {
|
|
||||||
return `space:${spaceId}:change-request:${changeRequestId}`;
|
|
||||||
}
|
|
||||||
@@ -1,13 +1,7 @@
|
|||||||
import { type ComputedContentSource, GitBookAPI } from '@gitbook/api';
|
import { type ComputedContentSource, GitBookAPI } from '@gitbook/api';
|
||||||
|
import { getCacheTag, getComputedContentSourceCacheTags } from '@gitbook/cache-tags';
|
||||||
import { GITBOOK_API_TOKEN, GITBOOK_API_URL, GITBOOK_USER_AGENT } from '@v2/lib/env';
|
import { GITBOOK_API_TOKEN, GITBOOK_API_URL, GITBOOK_USER_AGENT } from '@v2/lib/env';
|
||||||
import { unstable_cacheLife as cacheLife, unstable_cacheTag as cacheTag } from 'next/cache';
|
import { unstable_cacheLife as cacheLife, unstable_cacheTag as cacheTag } from 'next/cache';
|
||||||
import {
|
|
||||||
getChangeRequestCacheTag,
|
|
||||||
getHostnameCacheTag,
|
|
||||||
getOpenAPISpecCacheTag,
|
|
||||||
getSiteCacheTag,
|
|
||||||
getSpaceCacheTag,
|
|
||||||
} from '../cache';
|
|
||||||
import type { GitBookDataFetcher } from './types';
|
import type { GitBookDataFetcher } from './types';
|
||||||
|
|
||||||
interface DataFetcherInput {
|
interface DataFetcherInput {
|
||||||
@@ -125,6 +119,7 @@ export function createDataFetcher(input: DataFetcherInput = commonInput): GitBoo
|
|||||||
},
|
},
|
||||||
getComputedDocument(params) {
|
getComputedDocument(params) {
|
||||||
return getComputedDocument(input, {
|
return getComputedDocument(input, {
|
||||||
|
organizationId: params.organizationId,
|
||||||
spaceId: params.spaceId,
|
spaceId: params.spaceId,
|
||||||
source: params.source,
|
source: params.source,
|
||||||
});
|
});
|
||||||
@@ -183,7 +178,12 @@ async function getSpace(
|
|||||||
'use cache';
|
'use cache';
|
||||||
|
|
||||||
cacheLife('days');
|
cacheLife('days');
|
||||||
cacheTag(getSpaceCacheTag(params.spaceId));
|
cacheTag(
|
||||||
|
getCacheTag({
|
||||||
|
tag: 'space',
|
||||||
|
space: params.spaceId,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
const res = await getAPI(input).spaces.getSpaceById(params.spaceId, {
|
const res = await getAPI(input).spaces.getSpaceById(params.spaceId, {
|
||||||
shareKey: params.shareKey,
|
shareKey: params.shareKey,
|
||||||
@@ -207,7 +207,13 @@ async function getChangeRequest(
|
|||||||
params.spaceId,
|
params.spaceId,
|
||||||
params.changeRequestId
|
params.changeRequestId
|
||||||
);
|
);
|
||||||
cacheTag(getChangeRequestCacheTag(params.spaceId, res.data.id));
|
cacheTag(
|
||||||
|
getCacheTag({
|
||||||
|
tag: 'change-request',
|
||||||
|
space: params.spaceId,
|
||||||
|
changeRequest: res.data.id,
|
||||||
|
})
|
||||||
|
);
|
||||||
return res.data;
|
return res.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (checkHasErrorCode(error, 404)) {
|
if (checkHasErrorCode(error, 404)) {
|
||||||
@@ -335,14 +341,24 @@ async function getComputedDocument(
|
|||||||
input: DataFetcherInput,
|
input: DataFetcherInput,
|
||||||
params: {
|
params: {
|
||||||
spaceId: string;
|
spaceId: string;
|
||||||
|
organizationId: string;
|
||||||
source: ComputedContentSource;
|
source: ComputedContentSource;
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
'use cache';
|
'use cache';
|
||||||
|
|
||||||
// TODO: we need to resolve dependencies and pass them in the cache key
|
|
||||||
cacheLife('days');
|
cacheLife('days');
|
||||||
|
|
||||||
|
cacheTag(
|
||||||
|
...getComputedContentSourceCacheTags(
|
||||||
|
{
|
||||||
|
spaceId: params.spaceId,
|
||||||
|
organizationId: params.organizationId,
|
||||||
|
},
|
||||||
|
params.source
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
const res = await getAPI(input).spaces.getComputedDocument(params.spaceId, {
|
const res = await getAPI(input).spaces.getComputedDocument(params.spaceId, {
|
||||||
source: params.source,
|
source: params.source,
|
||||||
});
|
});
|
||||||
@@ -386,7 +402,13 @@ async function getLatestOpenAPISpecVersionContent(
|
|||||||
) {
|
) {
|
||||||
'use cache';
|
'use cache';
|
||||||
|
|
||||||
cacheTag(getOpenAPISpecCacheTag(params.organizationId, params.slug));
|
cacheTag(
|
||||||
|
getCacheTag({
|
||||||
|
tag: 'openapi',
|
||||||
|
organization: params.organizationId,
|
||||||
|
openAPISpec: params.slug,
|
||||||
|
})
|
||||||
|
);
|
||||||
cacheLife('days');
|
cacheLife('days');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -417,7 +439,12 @@ async function getPublishedContentByUrl(
|
|||||||
const { url, visitorAuthToken, redirectOnError } = params;
|
const { url, visitorAuthToken, redirectOnError } = params;
|
||||||
|
|
||||||
const hostname = new URL(url).hostname;
|
const hostname = new URL(url).hostname;
|
||||||
cacheTag(getHostnameCacheTag(hostname));
|
cacheTag(
|
||||||
|
getCacheTag({
|
||||||
|
tag: 'url',
|
||||||
|
hostname,
|
||||||
|
})
|
||||||
|
);
|
||||||
cacheLife('days');
|
cacheLife('days');
|
||||||
|
|
||||||
const res = await getAPI(input).urls.getPublishedContentByUrl({
|
const res = await getAPI(input).urls.getPublishedContentByUrl({
|
||||||
@@ -427,7 +454,12 @@ async function getPublishedContentByUrl(
|
|||||||
});
|
});
|
||||||
|
|
||||||
if ('site' in res.data) {
|
if ('site' in res.data) {
|
||||||
cacheTag(getSiteCacheTag(res.data.site));
|
cacheTag(
|
||||||
|
getCacheTag({
|
||||||
|
tag: 'site',
|
||||||
|
site: res.data.site,
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.data;
|
return res.data;
|
||||||
@@ -443,7 +475,12 @@ async function getPublishedContentSite(
|
|||||||
) {
|
) {
|
||||||
'use cache';
|
'use cache';
|
||||||
|
|
||||||
cacheTag(getSiteCacheTag(params.siteId));
|
cacheTag(
|
||||||
|
getCacheTag({
|
||||||
|
tag: 'site',
|
||||||
|
site: params.siteId,
|
||||||
|
})
|
||||||
|
);
|
||||||
cacheLife('days');
|
cacheLife('days');
|
||||||
|
|
||||||
const res = await getAPI(input).orgs.getPublishedContentSite(
|
const res = await getAPI(input).orgs.getPublishedContentSite(
|
||||||
@@ -467,7 +504,12 @@ async function getSiteRedirectBySource(
|
|||||||
) {
|
) {
|
||||||
'use cache';
|
'use cache';
|
||||||
|
|
||||||
cacheTag(getSiteCacheTag(params.siteId));
|
cacheTag(
|
||||||
|
getCacheTag({
|
||||||
|
tag: 'site',
|
||||||
|
site: params.siteId,
|
||||||
|
})
|
||||||
|
);
|
||||||
cacheLife('days');
|
cacheLife('days');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ export interface GitBookDataFetcher {
|
|||||||
* Get a computed document by its space ID and computed source.
|
* Get a computed document by its space ID and computed source.
|
||||||
*/
|
*/
|
||||||
getComputedDocument(params: {
|
getComputedDocument(params: {
|
||||||
|
organizationId: string;
|
||||||
spaceId: string;
|
spaceId: string;
|
||||||
source: api.ComputedContentSource;
|
source: api.ComputedContentSource;
|
||||||
}): Promise<api.JSONDocument>;
|
}): Promise<api.JSONDocument>;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { RevisionPageDocument } from '@gitbook/api';
|
import type { RevisionPageDocument, Space } from '@gitbook/api';
|
||||||
import type { GitBookDataFetcher } from './types';
|
import type { GitBookDataFetcher } from './types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -6,14 +6,18 @@ import type { GitBookDataFetcher } from './types';
|
|||||||
*/
|
*/
|
||||||
export async function getPageDocument(
|
export async function getPageDocument(
|
||||||
dataFetcher: GitBookDataFetcher,
|
dataFetcher: GitBookDataFetcher,
|
||||||
spaceId: string,
|
space: Space,
|
||||||
page: RevisionPageDocument
|
page: RevisionPageDocument
|
||||||
) {
|
) {
|
||||||
if (page.documentId) {
|
if (page.documentId) {
|
||||||
return dataFetcher.getDocument({ spaceId, documentId: page.documentId });
|
return dataFetcher.getDocument({ spaceId: space.id, documentId: page.documentId });
|
||||||
}
|
}
|
||||||
if (page.computed) {
|
if (page.computed) {
|
||||||
return dataFetcher.getComputedDocument({ spaceId, source: page.computed });
|
return dataFetcher.getComputedDocument({
|
||||||
|
organizationId: space.organization,
|
||||||
|
spaceId: space.id,
|
||||||
|
source: page.computed,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@gitbook/api": "0.96.1",
|
"@gitbook/api": "0.96.1",
|
||||||
"@gitbook/cache-do": "workspace:*",
|
"@gitbook/cache-do": "workspace:*",
|
||||||
|
"@gitbook/cache-tags": "workspace:*",
|
||||||
"@gitbook/colors": "workspace:*",
|
"@gitbook/colors": "workspace:*",
|
||||||
"@gitbook/emoji-codepoints": "workspace:*",
|
"@gitbook/emoji-codepoints": "workspace:*",
|
||||||
"@gitbook/icons": "workspace:*",
|
"@gitbook/icons": "workspace:*",
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ async function PDFPageDocument(props: {
|
|||||||
}) {
|
}) {
|
||||||
const { page, context } = props;
|
const { page, context } = props;
|
||||||
const { space } = context;
|
const { space } = context;
|
||||||
const document = await getPageDocument(context.dataFetcher, space.id, page);
|
const document = await getPageDocument(context.dataFetcher, space, page);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PrintPage id={getPagePDFContainerId(page)}>
|
<PrintPage id={getPagePDFContainerId(page)}>
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ export async function SitePage(props: SitePageProps) {
|
|||||||
const withSections = Boolean(sections && sections.list.length > 0);
|
const withSections = Boolean(sections && sections.list.length > 0);
|
||||||
const headerOffset = { sectionsHeader: withSections, topHeader: withTopHeader };
|
const headerOffset = { sectionsHeader: withSections, topHeader: withTopHeader };
|
||||||
|
|
||||||
const document = await getPageDocument(context.dataFetcher, context.space.id, page);
|
const document = await getPageDocument(context.dataFetcher, context.space, page);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
+33
-119
@@ -1,4 +1,5 @@
|
|||||||
import { AsyncLocalStorage } from 'node:async_hooks';
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
||||||
|
import { getCacheTag, getComputedContentSourceCacheTags } from '@gitbook/cache-tags';
|
||||||
import 'server-only';
|
import 'server-only';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -14,7 +15,6 @@ import {
|
|||||||
type RevisionReusableContent,
|
type RevisionReusableContent,
|
||||||
} from '@gitbook/api';
|
} from '@gitbook/api';
|
||||||
import type { GitBookDataFetcher } from '@v2/lib/data/types';
|
import type { GitBookDataFetcher } from '@v2/lib/data/types';
|
||||||
import assertNever from 'assert-never';
|
|
||||||
import { headers } from 'next/headers';
|
import { headers } from 'next/headers';
|
||||||
|
|
||||||
import { batch } from './async';
|
import { batch } from './async';
|
||||||
@@ -171,7 +171,7 @@ export type PublishedContentWithCache =
|
|||||||
export const getUserById = cache({
|
export const getUserById = cache({
|
||||||
name: 'api.getUserById',
|
name: 'api.getUserById',
|
||||||
tag: (userId) =>
|
tag: (userId) =>
|
||||||
getAPICacheTag({
|
getCacheTag({
|
||||||
tag: 'user',
|
tag: 'user',
|
||||||
user: userId,
|
user: userId,
|
||||||
}),
|
}),
|
||||||
@@ -204,7 +204,7 @@ export const getUserById = cache({
|
|||||||
export const getLatestOpenAPISpecVersionContent = cache({
|
export const getLatestOpenAPISpecVersionContent = cache({
|
||||||
name: 'api.getLatestOpenApiSpecVersionContent',
|
name: 'api.getLatestOpenApiSpecVersionContent',
|
||||||
tag: (organization, openAPISpec) =>
|
tag: (organization, openAPISpec) =>
|
||||||
getAPICacheTag({
|
getCacheTag({
|
||||||
tag: 'openapi',
|
tag: 'openapi',
|
||||||
organization,
|
organization,
|
||||||
openAPISpec,
|
openAPISpec,
|
||||||
@@ -240,7 +240,7 @@ export const getLatestOpenAPISpecVersionContent = cache({
|
|||||||
export const getPublishedContentByUrl = cache({
|
export const getPublishedContentByUrl = cache({
|
||||||
name: 'api.getPublishedContentByUrl.v4',
|
name: 'api.getPublishedContentByUrl.v4',
|
||||||
tag: (url) =>
|
tag: (url) =>
|
||||||
getAPICacheTag({
|
getCacheTag({
|
||||||
tag: 'url',
|
tag: 'url',
|
||||||
hostname: new URL(url).hostname,
|
hostname: new URL(url).hostname,
|
||||||
}),
|
}),
|
||||||
@@ -301,7 +301,7 @@ export const getPublishedContentByUrl = cache({
|
|||||||
*/
|
*/
|
||||||
export const getSpace = cache({
|
export const getSpace = cache({
|
||||||
name: 'api.getSpace',
|
name: 'api.getSpace',
|
||||||
tag: (spaceId) => getAPICacheTag({ tag: 'space', space: spaceId }),
|
tag: (spaceId) => getCacheTag({ tag: 'space', space: spaceId }),
|
||||||
get: async (spaceId: string, shareKey: string | undefined, options: CacheFunctionOptions) => {
|
get: async (spaceId: string, shareKey: string | undefined, options: CacheFunctionOptions) => {
|
||||||
const apiCtx = await api();
|
const apiCtx = await api();
|
||||||
const response = await apiCtx.client.spaces.getSpaceById(
|
const response = await apiCtx.client.spaces.getSpaceById(
|
||||||
@@ -330,7 +330,7 @@ function checkHasErrorCode(error: unknown, code: number) {
|
|||||||
export const getChangeRequest = cache({
|
export const getChangeRequest = cache({
|
||||||
name: 'api.getChangeRequest',
|
name: 'api.getChangeRequest',
|
||||||
tag: (spaceId, changeRequestId) =>
|
tag: (spaceId, changeRequestId) =>
|
||||||
getAPICacheTag({ tag: 'change-request', space: spaceId, changeRequest: changeRequestId }),
|
getCacheTag({ tag: 'change-request', space: spaceId, changeRequest: changeRequestId }),
|
||||||
get: async (spaceId: string, changeRequestId: string, options: CacheFunctionOptions) => {
|
get: async (spaceId: string, changeRequestId: string, options: CacheFunctionOptions) => {
|
||||||
const apiCtx = await api();
|
const apiCtx = await api();
|
||||||
try {
|
try {
|
||||||
@@ -379,7 +379,7 @@ const getAPIContextId = async () => {
|
|||||||
export const getRevision = cache({
|
export const getRevision = cache({
|
||||||
name: 'api.getRevision.v2',
|
name: 'api.getRevision.v2',
|
||||||
tag: (spaceId, revisionId) =>
|
tag: (spaceId, revisionId) =>
|
||||||
getAPICacheTag({ tag: 'revision', space: spaceId, revision: revisionId }),
|
getCacheTag({ tag: 'revision', space: spaceId, revision: revisionId }),
|
||||||
getKeySuffix: getAPIContextId,
|
getKeySuffix: getAPIContextId,
|
||||||
get: async (
|
get: async (
|
||||||
spaceId: string,
|
spaceId: string,
|
||||||
@@ -411,7 +411,7 @@ export const getRevision = cache({
|
|||||||
export const getRevisionPages = cache({
|
export const getRevisionPages = cache({
|
||||||
name: 'api.getRevisionPages.v4',
|
name: 'api.getRevisionPages.v4',
|
||||||
tag: (spaceId, revisionId) =>
|
tag: (spaceId, revisionId) =>
|
||||||
getAPICacheTag({ tag: 'revision', space: spaceId, revision: revisionId }),
|
getCacheTag({ tag: 'revision', space: spaceId, revision: revisionId }),
|
||||||
getKeySuffix: getAPIContextId,
|
getKeySuffix: getAPIContextId,
|
||||||
get: async (
|
get: async (
|
||||||
spaceId: string,
|
spaceId: string,
|
||||||
@@ -446,7 +446,7 @@ export const getRevisionPages = cache({
|
|||||||
export const getRevisionPageByPath = cache({
|
export const getRevisionPageByPath = cache({
|
||||||
name: 'api.getRevisionPageByPath.v3',
|
name: 'api.getRevisionPageByPath.v3',
|
||||||
tag: (spaceId, revisionId) =>
|
tag: (spaceId, revisionId) =>
|
||||||
getAPICacheTag({ tag: 'revision', space: spaceId, revision: revisionId }),
|
getCacheTag({ tag: 'revision', space: spaceId, revision: revisionId }),
|
||||||
getKeySuffix: getAPIContextId,
|
getKeySuffix: getAPIContextId,
|
||||||
get: async (
|
get: async (
|
||||||
spaceId: string,
|
spaceId: string,
|
||||||
@@ -492,7 +492,7 @@ export const getRevisionPageByPath = cache({
|
|||||||
const getRevisionFileById = cache({
|
const getRevisionFileById = cache({
|
||||||
name: 'api.getRevisionFile.v3',
|
name: 'api.getRevisionFile.v3',
|
||||||
tag: (spaceId, revisionId) =>
|
tag: (spaceId, revisionId) =>
|
||||||
getAPICacheTag({ tag: 'revision', space: spaceId, revision: revisionId }),
|
getCacheTag({ tag: 'revision', space: spaceId, revision: revisionId }),
|
||||||
get: async (
|
get: async (
|
||||||
spaceId: string,
|
spaceId: string,
|
||||||
revisionId: string,
|
revisionId: string,
|
||||||
@@ -528,7 +528,7 @@ const getRevisionFileById = cache({
|
|||||||
const getRevisionReusableContentById = cache({
|
const getRevisionReusableContentById = cache({
|
||||||
name: 'api.getRevisionReusableContentById.v1',
|
name: 'api.getRevisionReusableContentById.v1',
|
||||||
tag: (spaceId, revisionId) =>
|
tag: (spaceId, revisionId) =>
|
||||||
getAPICacheTag({ tag: 'revision', space: spaceId, revision: revisionId }),
|
getCacheTag({ tag: 'revision', space: spaceId, revision: revisionId }),
|
||||||
getKeySuffix: getAPIContextId,
|
getKeySuffix: getAPIContextId,
|
||||||
get: async (
|
get: async (
|
||||||
spaceId: string,
|
spaceId: string,
|
||||||
@@ -569,7 +569,7 @@ const getRevisionReusableContentById = cache({
|
|||||||
const getRevisionAllFiles = cache({
|
const getRevisionAllFiles = cache({
|
||||||
name: 'api.getRevisionAllFiles.v2',
|
name: 'api.getRevisionAllFiles.v2',
|
||||||
tag: (spaceId, revisionId) =>
|
tag: (spaceId, revisionId) =>
|
||||||
getAPICacheTag({ tag: 'revision', space: spaceId, revision: revisionId }),
|
getCacheTag({ tag: 'revision', space: spaceId, revision: revisionId }),
|
||||||
get: async (spaceId: string, revisionId: string, options: CacheFunctionOptions) => {
|
get: async (spaceId: string, revisionId: string, options: CacheFunctionOptions) => {
|
||||||
const response = await getAll(
|
const response = await getAll(
|
||||||
async (params) => {
|
async (params) => {
|
||||||
@@ -684,7 +684,7 @@ export const getReusableContent = async (
|
|||||||
export const getDocument = cache({
|
export const getDocument = cache({
|
||||||
name: 'api.getDocument.v2',
|
name: 'api.getDocument.v2',
|
||||||
tag: (spaceId, documentId) =>
|
tag: (spaceId, documentId) =>
|
||||||
getAPICacheTag({ tag: 'document', space: spaceId, document: documentId }),
|
getCacheTag({ tag: 'document', space: spaceId, document: documentId }),
|
||||||
getKeySuffix: getAPIContextId,
|
getKeySuffix: getAPIContextId,
|
||||||
get: async (spaceId: string, documentId: string, options: CacheFunctionOptions) => {
|
get: async (spaceId: string, documentId: string, options: CacheFunctionOptions) => {
|
||||||
const apiCtx = await api();
|
const apiCtx = await api();
|
||||||
@@ -712,14 +712,21 @@ export const getDocument = cache({
|
|||||||
*/
|
*/
|
||||||
export const getComputedDocument = cache({
|
export const getComputedDocument = cache({
|
||||||
name: 'api.getComputedDocument',
|
name: 'api.getComputedDocument',
|
||||||
tag: (spaceId, source) =>
|
tag: (organizationId, spaceId, source) =>
|
||||||
getAPICacheTag({
|
getComputedContentSourceCacheTags(
|
||||||
tag: 'computed-document',
|
{
|
||||||
space: spaceId,
|
organizationId,
|
||||||
integration: source.integration,
|
spaceId,
|
||||||
}),
|
},
|
||||||
|
source
|
||||||
|
)[0],
|
||||||
getKeySuffix: getAPIContextId,
|
getKeySuffix: getAPIContextId,
|
||||||
get: async (spaceId: string, source: ComputedContentSource, options: CacheFunctionOptions) => {
|
get: async (
|
||||||
|
_organizationId: string,
|
||||||
|
spaceId: string,
|
||||||
|
source: ComputedContentSource,
|
||||||
|
options: CacheFunctionOptions
|
||||||
|
) => {
|
||||||
const apiCtx = await api();
|
const apiCtx = await api();
|
||||||
const response = await apiCtx.client.spaces.getComputedDocument(
|
const response = await apiCtx.client.spaces.getComputedDocument(
|
||||||
spaceId,
|
spaceId,
|
||||||
@@ -750,7 +757,7 @@ function validateSiteRedirectSource(source: string) {
|
|||||||
*/
|
*/
|
||||||
export const getSiteRedirectBySource = cache({
|
export const getSiteRedirectBySource = cache({
|
||||||
name: 'api.getSiteRedirectBySource',
|
name: 'api.getSiteRedirectBySource',
|
||||||
tag: ({ siteId }) => getAPICacheTag({ tag: 'site', site: siteId }),
|
tag: ({ siteId }) => getCacheTag({ tag: 'site', site: siteId }),
|
||||||
getKeySuffix: getAPIContextId,
|
getKeySuffix: getAPIContextId,
|
||||||
get: async (
|
get: async (
|
||||||
args: {
|
args: {
|
||||||
@@ -811,7 +818,7 @@ export const getSiteRedirectBySource = cache({
|
|||||||
*/
|
*/
|
||||||
export const getSite = cache({
|
export const getSite = cache({
|
||||||
name: 'api.getSite',
|
name: 'api.getSite',
|
||||||
tag: (_organizationId, siteId) => getAPICacheTag({ tag: 'site', site: siteId }),
|
tag: (_organizationId, siteId) => getCacheTag({ tag: 'site', site: siteId }),
|
||||||
getKeySuffix: getAPIContextId,
|
getKeySuffix: getAPIContextId,
|
||||||
get: async (organizationId: string, siteId: string, options: CacheFunctionOptions) => {
|
get: async (organizationId: string, siteId: string, options: CacheFunctionOptions) => {
|
||||||
const apiCtx = await api();
|
const apiCtx = await api();
|
||||||
@@ -830,7 +837,7 @@ export const getSite = cache({
|
|||||||
*/
|
*/
|
||||||
export const getPublishedContentSite = cache({
|
export const getPublishedContentSite = cache({
|
||||||
name: 'api.getPublishedContentSite',
|
name: 'api.getPublishedContentSite',
|
||||||
tag: ({ siteId }) => getAPICacheTag({ tag: 'site', site: siteId }),
|
tag: ({ siteId }) => getCacheTag({ tag: 'site', site: siteId }),
|
||||||
getKeySuffix: getAPIContextId,
|
getKeySuffix: getAPIContextId,
|
||||||
get: async (
|
get: async (
|
||||||
args: {
|
args: {
|
||||||
@@ -907,7 +914,7 @@ export async function getSpaceContentData(
|
|||||||
*/
|
*/
|
||||||
export const searchSiteContent = cache({
|
export const searchSiteContent = cache({
|
||||||
name: 'api.searchSiteContent',
|
name: 'api.searchSiteContent',
|
||||||
tag: (_organizationId, siteId) => getAPICacheTag({ tag: 'site', site: siteId }),
|
tag: (_organizationId, siteId) => getCacheTag({ tag: 'site', site: siteId }),
|
||||||
getKeySuffix: getAPIContextId,
|
getKeySuffix: getAPIContextId,
|
||||||
get: async (
|
get: async (
|
||||||
organizationId: string,
|
organizationId: string,
|
||||||
@@ -947,7 +954,7 @@ export const searchSiteContent = cache({
|
|||||||
*/
|
*/
|
||||||
export const renderIntegrationUi = cache({
|
export const renderIntegrationUi = cache({
|
||||||
name: 'api.renderIntegrationUi',
|
name: 'api.renderIntegrationUi',
|
||||||
tag: (integrationName) => getAPICacheTag({ tag: 'integration', integration: integrationName }),
|
tag: (integrationName) => getCacheTag({ tag: 'integration', integration: integrationName }),
|
||||||
get: async (
|
get: async (
|
||||||
integrationName: string,
|
integrationName: string,
|
||||||
request: RequestRenderIntegrationUI,
|
request: RequestRenderIntegrationUI,
|
||||||
@@ -971,7 +978,7 @@ export const renderIntegrationUi = cache({
|
|||||||
*/
|
*/
|
||||||
export const getEmbedByUrlInSpace = cache({
|
export const getEmbedByUrlInSpace = cache({
|
||||||
name: 'api.getEmbedByUrlInSpace',
|
name: 'api.getEmbedByUrlInSpace',
|
||||||
tag: (spaceId) => getAPICacheTag({ tag: 'space', space: spaceId }),
|
tag: (spaceId) => getCacheTag({ tag: 'space', space: spaceId }),
|
||||||
get: async (spaceId: string, url: string, options: CacheFunctionOptions) => {
|
get: async (spaceId: string, url: string, options: CacheFunctionOptions) => {
|
||||||
const apiCtx = await api();
|
const apiCtx = await api();
|
||||||
const response = await apiCtx.client.spaces.getEmbedByUrlInSpace(
|
const response = await apiCtx.client.spaces.getEmbedByUrlInSpace(
|
||||||
@@ -986,99 +993,6 @@ export const getEmbedByUrlInSpace = cache({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a cache tag for the API.
|
|
||||||
*/
|
|
||||||
export function getAPICacheTag(
|
|
||||||
spec: // All data related to a user
|
|
||||||
| {
|
|
||||||
tag: 'user';
|
|
||||||
user: string;
|
|
||||||
}
|
|
||||||
// All data related to a space
|
|
||||||
| {
|
|
||||||
tag: 'space';
|
|
||||||
space: string;
|
|
||||||
}
|
|
||||||
// All data related to an integration
|
|
||||||
| {
|
|
||||||
tag: 'integration';
|
|
||||||
integration: string;
|
|
||||||
}
|
|
||||||
// All data related to a change request
|
|
||||||
| {
|
|
||||||
tag: 'change-request';
|
|
||||||
space: string;
|
|
||||||
changeRequest: string;
|
|
||||||
}
|
|
||||||
// Immutable data related to a revision
|
|
||||||
| {
|
|
||||||
tag: 'revision';
|
|
||||||
space: string;
|
|
||||||
revision: string;
|
|
||||||
}
|
|
||||||
// Immutable data related to a document
|
|
||||||
| {
|
|
||||||
tag: 'document';
|
|
||||||
space: string;
|
|
||||||
document: string;
|
|
||||||
}
|
|
||||||
// Immutable data related to a computed document
|
|
||||||
| {
|
|
||||||
tag: 'computed-document';
|
|
||||||
space: string;
|
|
||||||
integration: string;
|
|
||||||
}
|
|
||||||
// All data related to the URL of a content
|
|
||||||
| {
|
|
||||||
tag: 'url';
|
|
||||||
hostname: string;
|
|
||||||
}
|
|
||||||
// All data related to a collection
|
|
||||||
| {
|
|
||||||
tag: 'collection';
|
|
||||||
collection: string;
|
|
||||||
}
|
|
||||||
// All data related to a site
|
|
||||||
| {
|
|
||||||
tag: 'site';
|
|
||||||
site: string;
|
|
||||||
}
|
|
||||||
// All data related to an OpenAPI spec
|
|
||||||
| {
|
|
||||||
tag: 'openapi';
|
|
||||||
organization: string;
|
|
||||||
openAPISpec: string;
|
|
||||||
}
|
|
||||||
): string {
|
|
||||||
switch (spec.tag) {
|
|
||||||
case 'user':
|
|
||||||
return `user:${spec.user}`;
|
|
||||||
case 'url':
|
|
||||||
return `url:${spec.hostname}`;
|
|
||||||
case 'space':
|
|
||||||
return `space:${spec.space}`;
|
|
||||||
case 'change-request':
|
|
||||||
return `space:${spec.space}:change-request:${spec.changeRequest}`;
|
|
||||||
case 'revision':
|
|
||||||
return `space:${spec.space}:revision:${spec.revision}`;
|
|
||||||
case 'document':
|
|
||||||
return `space:${spec.space}:document:${spec.document}`;
|
|
||||||
case 'computed-document':
|
|
||||||
return `space:${spec.space}:computed-document:${spec.integration}`;
|
|
||||||
case 'collection':
|
|
||||||
return `collection:${spec.collection}`;
|
|
||||||
case 'site':
|
|
||||||
return `site:${spec.site}`;
|
|
||||||
case 'integration':
|
|
||||||
return `integration:${spec.integration}`;
|
|
||||||
case 'openapi':
|
|
||||||
return `organization:${spec.organization}:openapi:${spec.openAPISpec}`;
|
|
||||||
default:
|
|
||||||
assertNever(spec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the user agent to use for API requests.
|
* Return the user agent to use for API requests.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ export async function resolveContentRef(
|
|||||||
text = `#${anchor}`;
|
text = `#${anchor}`;
|
||||||
|
|
||||||
if (resolveAnchorText) {
|
if (resolveAnchorText) {
|
||||||
const document = await getPageDocument(dataFetcher, space.id, page);
|
const document = await getPageDocument(dataFetcher, space, page);
|
||||||
if (document) {
|
if (document) {
|
||||||
const block = getBlockById(document, anchor);
|
const block = getBlockById(document, anchor);
|
||||||
if (block) {
|
if (block) {
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ async function getDataFetcherV1(): Promise<GitBookDataFetcher> {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getComputedDocument(params) {
|
getComputedDocument(params) {
|
||||||
return getComputedDocument(params.spaceId, params.source);
|
return getComputedDocument(params.organizationId, params.spaceId, params.source);
|
||||||
},
|
},
|
||||||
|
|
||||||
getRevisionPages(params) {
|
getRevisionPages(params) {
|
||||||
|
|||||||
Reference in New Issue
Block a user