first commit
This commit is contained in:
96
calcom/packages/trpc/server/createNextApiHandler.ts
Normal file
96
calcom/packages/trpc/server/createNextApiHandler.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import type { AnyRouter } from "@trpc/server";
|
||||
import { createNextApiHandler as _createNextApiHandler } from "@trpc/server/adapters/next";
|
||||
|
||||
import { createContext as createTrpcContext } from "./createContext";
|
||||
|
||||
/**
|
||||
* Creates an API handler executed by Next.js.
|
||||
*/
|
||||
export function createNextApiHandler(router: AnyRouter, isPublic = false, namespace = "") {
|
||||
return _createNextApiHandler({
|
||||
router,
|
||||
/**
|
||||
* @link https://trpc.io/docs/context
|
||||
*/
|
||||
createContext: (opts) => {
|
||||
return createTrpcContext(opts);
|
||||
},
|
||||
/**
|
||||
* @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 }) {
|
||||
const allOk = errors.length === 0;
|
||||
const isQuery = type === "query";
|
||||
const noHeaders = {};
|
||||
|
||||
// We cannot set headers on SSG queries
|
||||
if (!ctx?.res) return noHeaders;
|
||||
|
||||
const defaultHeaders: Record<"headers", Record<string, string>> = {
|
||||
headers: {},
|
||||
};
|
||||
|
||||
const timezone = z.string().safeParse(ctx.req?.headers["x-vercel-ip-timezone"]);
|
||||
if (timezone.success) defaultHeaders.headers["x-cal-timezone"] = timezone.data;
|
||||
|
||||
// We need all these conditions to be true to set cache headers
|
||||
if (!(isPublic && allOk && isQuery)) return defaultHeaders;
|
||||
|
||||
// No cache by default
|
||||
defaultHeaders.headers["cache-control"] = `no-cache`;
|
||||
|
||||
if (isPublic && paths) {
|
||||
const FIVE_MINUTES_IN_SECONDS = 5 * 60;
|
||||
const ONE_YEAR_IN_SECONDS = 31536000;
|
||||
const SETTING_FOR_CACHED_BY_VERSION =
|
||||
process.env.NODE_ENV === "development" ? "no-cache" : `max-age=${ONE_YEAR_IN_SECONDS}`;
|
||||
|
||||
const cacheRules = {
|
||||
session: "no-cache",
|
||||
|
||||
// i18n and cityTimezones are now being accessed using the CalComVersion, which updates on every release,
|
||||
// letting the clients get the new versions when the version number changes.
|
||||
i18n: SETTING_FOR_CACHED_BY_VERSION,
|
||||
cityTimezones: SETTING_FOR_CACHED_BY_VERSION,
|
||||
|
||||
// FIXME: Using `max-age=1, stale-while-revalidate=60` fails some booking tests.
|
||||
"slots.getSchedule": `no-cache`,
|
||||
|
||||
// Feature Flags change but it might be okay to have a 5 minute cache to avoid burdening the servers with requests for this.
|
||||
// Note that feature flags can be used to quickly kill a feature if it's not working as expected. So, we have to keep fresh time lesser than the deployment time atleast
|
||||
"features.map": `max-age=${FIVE_MINUTES_IN_SECONDS}, stale-while-revalidate=60`, // "map" - Feature Flag Map
|
||||
} as const;
|
||||
|
||||
const prependNamespace = (key: string) =>
|
||||
(namespace ? `${namespace}.${key}` : key) as keyof typeof cacheRules;
|
||||
const matchedPath = paths.find((v) => prependNamespace(v) in cacheRules);
|
||||
if (matchedPath) {
|
||||
const cacheRule = cacheRules[prependNamespace(matchedPath)];
|
||||
|
||||
// We must set cdn-cache-control as well to ensure that Vercel doesn't strip stale-while-revalidate
|
||||
// https://vercel.com/docs/concepts/edge-network/caching#:~:text=If%20you%20set,in%20the%20response.
|
||||
defaultHeaders.headers["cache-control"] = defaultHeaders.headers["cdn-cache-control"] = cacheRule;
|
||||
}
|
||||
}
|
||||
|
||||
return defaultHeaders;
|
||||
},
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user