Add 'revalidate' route, add DIRECTUS_REVALIDATE_KEY

This commit is contained in:
2024-12-19 16:36:19 -06:00
parent dcc9134dad
commit 5413fef3e3
3 changed files with 104 additions and 0 deletions

View File

@@ -9,3 +9,4 @@
# Example:
# SERVERVAR=foo
# NEXT_PUBLIC_CLIENTVAR=bar
DIRECTUS_REVALIDATE_KEY=

1
src/env/schema.mjs vendored
View File

@@ -6,6 +6,7 @@ import { z } from "zod";
* This way you can ensure the app isn't built with invalid env vars.
*/
export const serverSchema = z.object({
DIRECTUS_REVALIDATE_KEY: z.string(),
NODE_ENV: z.enum(["development", "test", "production"]),
});

102
src/pages/api/revalidate.ts Normal file
View File

@@ -0,0 +1,102 @@
import { readItem, readItems } from "@directus/sdk";
import type { NextApiRequest, NextApiResponse } from "next";
import { z } from "zod";
import directus from "../../utils/directus";
async function getURLs(
type: string,
key: string,
payload: Map<string, unknown>,
): Promise<string[] | null> {
if (type == "project_link" || type == "project_technology") {
console.error({
message: `Failed to provide URls for '${type}' type`,
type,
key,
payload,
});
return [];
}
if (type === "project") return ["/projects", `/projects/${key}`];
if (type === "metadata") return ["/"];
if (type === "technology") {
const urls = ["/technology"];
// Get all projects with the technology
const all_projects = await directus.request(readItems("project"));
if (all_projects != null) {
for (const project of all_projects) {
if (project.technologies?.some((t) => t.id === key))
urls.push(`/projects/${project.id}`);
}
}
return urls;
}
if (type === "projects") {
const urls = ["/projects", `/projects/${key}`];
// TODO: If 'featured', index page should be revalidated
const project = await directus.request(readItem("project", key));
if (project != null) return urls;
}
return null;
}
const requestSchema = z.object({
type: z.string(),
keys: z.array(z.string()).min(1),
source: z.map(z.string(), z.any()),
payload: z.map(z.string(), z.any()),
});
export default async function handler(
req: NextApiRequest,
res: NextApiResponse,
) {
if (req.method !== "POST")
return res.status(405).json({ message: "Method not allowed" });
if (
req.headers["Authorization"] !==
"Bearer " + process.env.DIRECTUS_REVALIDATE_KEY
)
return res.status(401).json({ message: "Invalid token" });
try {
// Verify JSON body
const { success, data } = requestSchema.safeParse(req.body);
if (!success) return res.status(400).json({ message: "Invalid JSON body" });
// Get URLs
const urls = await getURLs(data.type, data.keys[0]!, data.payload);
if (urls === null)
return res
.status(404)
.json({ revalidated: false, message: "Collection not found" });
// Revalidate all URLs
try {
await Promise.all(urls.map((url) => res.revalidate(url)));
} catch (error) {
console.error({ message: "Error while revalidating", error });
return res.status(500).json({
revalidated: false,
message: "Error while revalidating",
urls,
});
}
// Return success
return res.json({ revalidated: true, urls });
} catch (error) {
console.error({
message: "Error while preparing to revalidate",
error,
});
return res.status(500).send("Error revalidating");
}
}