cal.pub0.org/apps/web/pages/api/trpc/[trpc].ts

94 lines
3.0 KiB
TypeScript

/**
* This file contains tRPC's HTTP response handler
*/
import { z } from "zod";
import * as trpcNext from "@calcom/trpc/server/adapters/next";
import { createContext } from "@calcom/trpc/server/createContext";
import { appRouter } from "@calcom/trpc/server/routers/_app";
export default trpcNext.createNextApiHandler({
router: appRouter,
/**
* @link https://trpc.io/docs/context
*/
createContext,
/**
* @link https://trpc.io/docs/error-handling
*/
onError({ error }) {
if (error.code === "INTERNAL_SERVER_ERROR") {
// send to bug reporting
console.error("Something went wrong", error);
}
},
/**
* Enable query batching
*/
batching: {
enabled: true,
},
/**
* @link https://trpc.io/docs/caching#api-response-caching
*/
responseMeta({ ctx, paths, type, errors }) {
// Some helpers relevant to this function only
const ONE_DAY_IN_SECONDS = 60 * 60 * 24;
const TWO_HOURS_IN_SECONDS = 60 * 60 * 2;
// Our response to indicate no caching
const defaultHeaders: Record<"headers", Record<string, string>> = {
headers: {},
};
if (!!ctx?.req) {
const timezone = z.string().safeParse(ctx.req.headers["x-vercel-ip-timezone"]);
if (timezone.success) defaultHeaders.headers["x-cal-timezone"] = timezone.data;
}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore ctx.req is available for SSR but not SSG
if (!!ctx?.req) {
return defaultHeaders;
}
// No caching if we have a non-public path
// Assuming we have all our public routes in `viewer.public`
if (!paths || !paths.every((path) => path.startsWith("viewer.public."))) {
return defaultHeaders;
}
// No caching if we have any procedures errored
if (errors.length !== 0) {
return defaultHeaders;
}
// Never cache non-queries (aka mutations)
if (type !== "query") {
return defaultHeaders;
}
// cache request for 1 day + revalidate once every 5 seconds
let cacheValue = `s-maxage=${ONE_DAY_IN_SECONDS}, stale-while-revalidate=5`;
// Our cache can change depending on our current paths value. Since paths is an array,
// we want to create a map that can match potential paths with their desired cache value
const cacheRules = {
"viewer.public.i18n": `maxage=${TWO_HOURS_IN_SECONDS}, stale-while-revalidate=30`,
// Revalidation time here should be 1 second, per https://github.com/calcom/cal.com/pull/6823#issuecomment-1423215321
"viewer.public.slots.getSchedule": `s-maxage=5, stale-while-revalidate=1`,
} as const;
// Find which element above is an exact match for this group of paths
const matchedPath = paths.find((v) => v in cacheRules) as keyof typeof cacheRules;
// Get the cache value of the matching element, if any
if (matchedPath) cacheValue = cacheRules[matchedPath];
if (cacheValue) defaultHeaders.headers["Cache-Control"] = cacheValue;
// Finally we respond with our resolved cache value
return defaultHeaders;
},
});