Skip to content

Commit

Permalink
revalidate-all/v3 (#724)
Browse files Browse the repository at this point in the history
  • Loading branch information
abvthecity authored Apr 29, 2024
1 parent f5cbfd1 commit 3ecc6ea
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 6 deletions.
22 changes: 22 additions & 0 deletions fern/apis/revalidation/definition/__package__.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,28 @@ service:
docs: |
The host you want to revalidate the docs for.
response: RevalidateAllV2Response
revalidateAllV3:
path: /revalidate-all/v3
docs: Revalidates a docs website
display-name: Revalidate a docs instance
method: GET
request:
name: CreateRevalidateAllV3Request
headers:
x-fern-host:
type: string
docs: |
The host you want to revalidate the docs for.
query-parameters:
host:
type: string
docs: |
The host you want to revalidate the docs for.
basePath:
type: string
docs: |
The base path of the docs you want to revalidate.
response: RevalidateAllV2Response

types:
RevalidateAllV2Response:
Expand Down
128 changes: 128 additions & 0 deletions packages/ui/docs-bundle/src/pages/api/fern-docs/revalidate-all/v3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import { buildUrl, getAllUrlsFromDocsConfig } from "@fern-ui/fdr-utils";
import { NextApiHandler, NextApiRequest, NextApiResponse } from "next";
import { loadWithUrl } from "../../../../utils/loadWithUrl";
import { toValidPathname } from "../../../../utils/toValidPathname";

function getHostFromUrl(url: string | undefined): string | undefined {
if (url == null) {
return undefined;
}
const urlObj = new URL(url);
return urlObj.host;
}

export const config = {
maxDuration: 300,
};

type RevalidatePathResult = RevalidatePathSuccessResult | RevalidatePathErrorResult;

interface RevalidatePathSuccessResult {
success: true;
url: string;
}

function isSuccessResult(result: RevalidatePathResult): result is RevalidatePathSuccessResult {
return result.success;
}

interface RevalidatePathErrorResult {
success: false;
url: string;
message: string;
}

function isFailureResult(result: RevalidatePathResult): result is RevalidatePathErrorResult {
return !result.success;
}

type RevalidatedPaths = {
successfulRevalidations: RevalidatePathSuccessResult[];
failedRevalidations: RevalidatePathErrorResult[];
};

const handler: NextApiHandler = async (
req: NextApiRequest,
res: NextApiResponse<RevalidatedPaths>,
): Promise<unknown> => {
// if (req.method !== "POST") {
// return res.status(405).json({ successfulRevalidations: [], failedRevalidations: [] });
// }
try {
// when we call res.revalidate() nextjs uses
// req.headers.host to make the network request
const xFernHost = getHost(req.query.host) ?? req.headers["x-fern-host"] ?? getHostFromUrl(req.url);
if (typeof xFernHost !== "string") {
return res.status(404).json({ successfulRevalidations: [], failedRevalidations: [] });
}
const hostWithoutTrailingSlash = xFernHost.endsWith("/") ? xFernHost.slice(0, -1) : xFernHost;

const url = buildUrl({
host: hostWithoutTrailingSlash,
pathname: toValidPathname(req.query.basePath),
});
// eslint-disable-next-line no-console
console.log("[revalidate-all/v2] Loading docs for", url);
const docs = await loadWithUrl(url);

if (docs == null) {
// return notFoundResponse();
return res.status(404).json({ successfulRevalidations: [], failedRevalidations: [] });
}

const urls = getAllUrlsFromDocsConfig(
xFernHost,
docs.baseUrl.basePath,
docs.definition.config.navigation,
docs.definition.apis,
);

// when we call res.revalidate() nextjs uses
// req.headers.host to make the network request
req.headers.host = xFernHost;

const results: RevalidatePathResult[] = [];

const batchSize = 250;
for (let i = 0; i < urls.length; i += batchSize) {
const batch = urls.slice(i, i + batchSize);
results.push(
...(await Promise.all(
batch.map(async (url): Promise<RevalidatePathResult> => {
// eslint-disable-next-line no-console
console.log(`Revalidating ${url}`);
try {
await res.revalidate(`/static/${encodeURI(url)}`);
return { success: true, url };
} catch (e) {
// eslint-disable-next-line no-console
console.error(e);
return { success: false, url, message: e instanceof Error ? e.message : "Unknown error." };
}
}),
)),
);
}

const successfulRevalidations = results.filter(isSuccessResult);
const failedRevalidations = results.filter(isFailureResult);

return res
.status(failedRevalidations.length === 0 ? 200 : successfulRevalidations.length === 0 ? 500 : 207)
.json({ successfulRevalidations, failedRevalidations });
} catch (err) {
// eslint-disable-next-line no-console
console.error(err);
return res.status(500).json({ successfulRevalidations: [], failedRevalidations: [] });
}
};

export default handler;

function getHost(maybeHost: string | string[] | undefined): string | undefined {
if (typeof maybeHost === "string") {
return maybeHost;
}

return undefined;
}
8 changes: 4 additions & 4 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion servers/fdr/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"@fern-api/template-resolver": "workspace:*",
"@fern-api/fdr-sdk": "workspace:*",
"@fern-api/venus-api-sdk": "^0.3.0-2-g994ae9e",
"@fern-fern/revalidation-sdk": "0.0.7",
"@fern-fern/revalidation-sdk": "0.0.9",
"@prisma/client": "5.13.0",
"@sentry/cli": "^2.31.0",
"@sentry/node": "^7.112.2",
Expand Down
2 changes: 1 addition & 1 deletion servers/fdr/src/services/revalidator/RevalidatorService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export class RevalidatorServiceImpl implements RevalidatorService {
environment: baseUrl.toURL().toString(),
});
app?.logger.log("Revalidating paths at", baseUrl.toURL().toString());
const response = await client.revalidateAllV2({
const response = await client.revalidateAllV3({
host: baseUrl.hostname,
basePath: baseUrl.path != null ? baseUrl.path : "",
xFernHost: baseUrl.hostname,
Expand Down

0 comments on commit 3ecc6ea

Please sign in to comment.