chore: [app-router-migration 39] refactor ssr/ssg functions (#13336)

This commit is contained in:
DmytroHryshyn
2024-01-19 15:58:37 -07:00
committed by GitHub
parent 5685d343b1
commit ff1aefe539
21 changed files with 168 additions and 81 deletions
+3 -3
View File
@@ -2,13 +2,13 @@ import NotFoundPage from "@pages/404";
import { WithLayout } from "app/layoutHOC";
import type { GetStaticPropsContext } from "next";
import { ssgInit } from "@server/lib/ssg";
import { getTranslations } from "@server/lib/getTranslations";
const getData = async (context: GetStaticPropsContext) => {
const ssg = await ssgInit(context);
const i18n = await getTranslations(context);
return {
dehydratedState: ssg.dehydrate(),
i18n,
};
};
+2 -1
View File
@@ -37,6 +37,7 @@ export type AppProps = Omit<
WithNonceProps<{
themeBasis?: string;
session: Session;
i18n?: SSRConfig;
}>
>
>,
@@ -108,7 +109,7 @@ const CustomI18nextProvider = (props: AppPropsWithoutNonce) => {
}, [locale]);
const clientViewerI18n = useViewerI18n(locale);
const i18n = clientViewerI18n.data?.i18n;
const i18n = clientViewerI18n.data?.i18n ?? props.pageProps.i18n;
const passedProps = {
...props,
@@ -1,7 +1,7 @@
import { type GetStaticProps } from "next";
import { z } from "zod";
import { ssgInit } from "@server/lib/ssg";
import { getTranslations } from "@server/lib/getTranslations";
const validStatuses = ["upcoming", "recurring", "past", "cancelled", "unconfirmed"] as const;
@@ -11,14 +11,14 @@ const querySchema = z.object({
export const getStaticProps: GetStaticProps = async (ctx) => {
const params = querySchema.safeParse(ctx.params);
const ssg = await ssgInit(ctx);
const i18n = await getTranslations(ctx);
if (!params.success) return { notFound: true };
return {
props: {
status: params.data.status,
trpcState: ssg.dehydrate(),
i18n,
},
};
};
+3 -3
View File
@@ -17,7 +17,7 @@ import { Discord } from "@calcom/ui/components/icon/Discord";
import PageWrapper from "@components/PageWrapper";
import { ssgInit } from "@server/lib/ssg";
import { getTranslations } from "@server/lib/getTranslations";
enum pageType {
ORG = "org",
@@ -273,11 +273,11 @@ export default function Custom404() {
Custom404.PageWrapper = PageWrapper;
export const getStaticProps = async (context: GetStaticPropsContext) => {
const ssr = await ssgInit(context);
const i18n = await getTranslations(context);
return {
props: {
trpcState: ssr.dehydrate(),
i18n,
},
};
};
+3 -3
View File
@@ -10,7 +10,7 @@ import { X } from "@calcom/ui/components/icon";
import PageWrapper from "@components/PageWrapper";
import AuthContainer from "@components/ui/AuthContainer";
import { ssgInit } from "@server/lib/ssg";
import { getTranslations } from "@server/lib/getTranslations";
const querySchema = z.object({
error: z.string().optional(),
@@ -50,11 +50,11 @@ export default function Error() {
Error.PageWrapper = PageWrapper;
export const getStaticProps = async (context: GetStaticPropsContext) => {
const ssr = await ssgInit(context);
const i18n = await getTranslations(context);
return {
props: {
trpcState: ssr.dehydrate(),
i18n,
},
};
};
+22
View File
@@ -0,0 +1,22 @@
import type { GetStaticPropsContext } from "next";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { i18n } = require("@calcom/config/next-i18next.config");
export async function getTranslations<TParams extends { locale?: string }>(
opts: GetStaticPropsContext<TParams>
) {
const requestedLocale = opts.params?.locale || opts.locale || i18n.defaultLocale;
const isSupportedLocale = i18n.locales.includes(requestedLocale);
if (!isSupportedLocale) {
console.warn(`Requested unsupported locale "${requestedLocale}"`);
}
const locale = isSupportedLocale ? requestedLocale : i18n.defaultLocale;
const _i18n = await serverSideTranslations(locale, ["common"]);
return {
i18n: _i18n,
};
}
+42 -2
View File
@@ -2,11 +2,51 @@ import type { GetServerSidePropsContext } from "next";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import superjson from "superjson";
import { forms } from "@calcom/app-store/routing-forms/trpc/procedures/forms";
import { getLocale } from "@calcom/features/auth/lib/getLocale";
import { map } from "@calcom/features/flags/server/procedures/map";
import { CALCOM_VERSION } from "@calcom/lib/constants";
import { createProxySSGHelpers } from "@calcom/trpc/react/ssg";
import { createContext } from "@calcom/trpc/server/createContext";
import { appRouter } from "@calcom/trpc/server/routers/_app";
import { me } from "@calcom/trpc/server/routers/loggedInViewer/procedures/me";
import { teamsAndUserProfilesQuery } from "@calcom/trpc/server/routers/loggedInViewer/procedures/teamsAndUserProfilesQuery";
import { event } from "@calcom/trpc/server/routers/publicViewer/procedures/event";
import { session } from "@calcom/trpc/server/routers/publicViewer/procedures/session";
import { get } from "@calcom/trpc/server/routers/viewer/eventTypes/procedures/get";
import { hasTeamPlan } from "@calcom/trpc/server/routers/viewer/teams/procedures/hasTeamPlan";
import { router, mergeRouters } from "@calcom/trpc/server/trpc";
const loggedInRouter = router({
me,
});
// Temporary workaround for OOM issue, import only procedures that are called on the server side
const routerSlice = router({
viewer: mergeRouters(
loggedInRouter,
router({
features: router({
map,
}),
public: router({
session,
event,
}),
teams: router({
hasTeamPlan,
}),
appRoutingForms: router({
forms,
}),
teamsAndUserProfilesQuery: router({
teamsAndUserProfilesQuery,
}),
eventTypes: router({
get,
}),
})
),
});
/**
* Initialize server-side rendering tRPC helpers.
@@ -20,7 +60,7 @@ export async function ssrInit(context: GetServerSidePropsContext, options?: { no
const i18n = await serverSideTranslations(locale, ["common", "vital"]);
const ssr = createProxySSGHelpers({
router: appRouter,
router: routerSlice,
transformer: superjson,
ctx: { ...ctx, locale, i18n },
});
@@ -5,7 +5,7 @@ import { router } from "@calcom/trpc/server/trpc";
import { ZDeleteFormInputSchema } from "./deleteForm.schema";
import { ZFormMutationInputSchema } from "./formMutation.schema";
import { ZFormQueryInputSchema } from "./formQuery.schema";
import { ZFormsInputSchema } from "./forms.schema";
import { forms } from "./procedures/forms";
import { ZReportInputSchema } from "./report.schema";
import { ZResponseInputSchema } from "./response.schema";
@@ -50,10 +50,7 @@ const appRoutingForms = router({
return handler({ ctx, input });
}),
}),
forms: authedProcedure.input(ZFormsInputSchema).query(async ({ ctx, input }) => {
const handler = await getHandler("forms", () => import("./forms.handler"));
return handler({ ctx, input });
}),
forms,
formQuery: authedProcedure.input(ZFormQueryInputSchema).query(async ({ ctx, input }) => {
const handler = await getHandler("formQuery", () => import("./formQuery.handler"));
return handler({ ctx, input });
@@ -0,0 +1,8 @@
import authedProcedure from "@calcom/trpc/server/procedures/authedProcedure";
import { ZFormsInputSchema } from "../forms.schema";
export const forms = authedProcedure.input(ZFormsInputSchema).query(async ({ ctx, input }) => {
const handler = (await import("../forms.handler")).default;
return handler({ ctx, input });
});
@@ -0,0 +1,8 @@
import publicProcedure from "@calcom/trpc/server/procedures/publicProcedure";
import { getFeatureFlagMap } from "../utils";
export const map = publicProcedure.query(async ({ ctx }) => {
const { prisma } = ctx;
return getFeatureFlagMap(prisma);
});
+2 -5
View File
@@ -1,7 +1,7 @@
import publicProcedure from "@calcom/trpc/server/procedures/publicProcedure";
import { router } from "@calcom/trpc/server/trpc";
import { getFeatureFlagMap } from "./utils";
import { map } from "./procedures/map";
export const featureFlagRouter = router({
list: publicProcedure.query(async ({ ctx }) => {
@@ -11,8 +11,5 @@ export const featureFlagRouter = router({
cacheStrategy: { swr: 300, ttl: 300 },
});
}),
map: publicProcedure.query(async ({ ctx }) => {
const { prisma } = ctx;
return getFeatureFlagMap(prisma);
}),
map,
});
@@ -13,6 +13,8 @@ import { ZGetDownloadLinkOfCalVideoRecordingsInputSchema } from "./getDownloadLi
import { ZIntegrationsInputSchema } from "./integrations.schema";
import { ZLocationOptionsInputSchema } from "./locationOptions.schema";
import { ZOutOfOfficeInputSchema, ZOutOfOfficeDelete } from "./outOfOffice.schema";
import { me } from "./procedures/me";
import { teamsAndUserProfilesQuery } from "./procedures/teamsAndUserProfilesQuery";
import { ZRoutingFormOrderInputSchema } from "./routingFormOrder.schema";
import { ZSetDestinationCalendarInputSchema } from "./setDestinationCalendar.schema";
import { ZSubmitFeedbackInputSchema } from "./submitFeedback.schema";
@@ -56,18 +58,7 @@ type AppsRouterHandlerCache = {
const UNSTABLE_HANDLER_CACHE: AppsRouterHandlerCache = {};
export const loggedInViewerRouter = router({
me: authedProcedure.query(async ({ ctx }) => {
if (!UNSTABLE_HANDLER_CACHE.me) {
UNSTABLE_HANDLER_CACHE.me = (await import("./me.handler")).meHandler;
}
// Unreachable code but required for type safety
if (!UNSTABLE_HANDLER_CACHE.me) {
throw new Error("Failed to load handler");
}
return UNSTABLE_HANDLER_CACHE.me({ ctx });
}),
me,
avatar: authedProcedure.query(async ({ ctx }) => {
if (!UNSTABLE_HANDLER_CACHE.avatar) {
@@ -424,20 +415,7 @@ export const loggedInViewerRouter = router({
return UNSTABLE_HANDLER_CACHE.shouldVerifyEmail({ ctx });
}),
teamsAndUserProfilesQuery: authedProcedure.query(async ({ ctx }) => {
if (!UNSTABLE_HANDLER_CACHE.teamsAndUserProfilesQuery) {
UNSTABLE_HANDLER_CACHE.teamsAndUserProfilesQuery = (
await import("./teamsAndUserProfilesQuery.handler")
).teamsAndUserProfilesQuery;
}
// Unreachable code but required for type safety
if (!UNSTABLE_HANDLER_CACHE.teamsAndUserProfilesQuery) {
throw new Error("Failed to load handler");
}
return UNSTABLE_HANDLER_CACHE.teamsAndUserProfilesQuery({ ctx });
}),
teamsAndUserProfilesQuery,
connectAndJoin: authedProcedure.input(ZConnectAndJoinInputSchema).mutation(async ({ ctx, input }) => {
if (!UNSTABLE_HANDLER_CACHE.connectAndJoin) {
UNSTABLE_HANDLER_CACHE.connectAndJoin = (await import("./connectAndJoin.handler")).Handler;
@@ -0,0 +1,7 @@
import authedProcedure from "../../../procedures/authedProcedure";
export const me = authedProcedure.query(async ({ ctx }) => {
const handler = (await import("../me.handler")).meHandler;
return handler({ ctx });
});
@@ -0,0 +1,7 @@
import authedProcedure from "../../../procedures/authedProcedure";
export const teamsAndUserProfilesQuery = authedProcedure.query(async ({ ctx }) => {
const handler = (await import("../teamsAndUserProfilesQuery.handler")).teamsAndUserProfilesQuery;
return handler({ ctx });
});
@@ -1,9 +1,9 @@
import sessionMiddleware from "../../middlewares/sessionMiddleware";
import publicProcedure from "../../procedures/publicProcedure";
import { importHandler, router } from "../../trpc";
import { slotsRouter } from "../viewer/slots/_router";
import { ZEventInputSchema } from "./event.schema";
import { i18nInputSchema } from "./i18n.schema";
import { event } from "./procedures/event";
import { session } from "./procedures/session";
import { ZSamlTenantProductInputSchema } from "./samlTenantProduct.schema";
import { ZStripeCheckoutSessionInputSchema } from "./stripeCheckoutSession.schema";
@@ -13,10 +13,7 @@ const namespaced = (s: string) => `${NAMESPACE}.${s}`;
// things that unauthenticated users can query about themselves
export const publicViewerRouter = router({
session: publicProcedure.use(sessionMiddleware).query(async (opts) => {
const handler = await importHandler(namespaced("session"), () => import("./session.handler"));
return handler(opts);
}),
session,
i18n: publicProcedure.input(i18nInputSchema).query(async (opts) => {
const handler = await importHandler(namespaced("i18n"), () => import("./i18n.handler"));
return handler(opts);
@@ -45,10 +42,7 @@ export const publicViewerRouter = router({
}),
// REVIEW: This router is part of both the public and private viewer router?
slots: slotsRouter,
event: publicProcedure.input(ZEventInputSchema).query(async (opts) => {
const handler = await importHandler(namespaced("event"), () => import("./event.handler"));
return handler(opts);
}),
event,
ssoConnections: publicProcedure.query(async () => {
const handler = await importHandler(
namespaced("ssoConnections"),
@@ -0,0 +1,11 @@
import publicProcedure from "../../../procedures/publicProcedure";
import { importHandler } from "../../../trpc";
import { ZEventInputSchema } from "../event.schema";
const NAMESPACE = "publicViewer";
const namespaced = (s: string) => `${NAMESPACE}.${s}`;
export const event = publicProcedure.input(ZEventInputSchema).query(async (opts) => {
const handler = await importHandler(namespaced("event"), () => import("../event.handler"));
return handler(opts);
});
@@ -0,0 +1,12 @@
import sessionMiddleware from "../../../middlewares/sessionMiddleware";
import publicProcedure from "../../../procedures/publicProcedure";
import { importHandler } from "../../../trpc";
const NAMESPACE = "publicViewer";
const namespaced = (s: string) => `${NAMESPACE}.${s}`;
export const session = publicProcedure.use(sessionMiddleware).query(async (opts) => {
const handler = await importHandler(namespaced("session"), () => import("../session.handler"));
return handler(opts);
});
@@ -7,8 +7,8 @@ import { router } from "../../../trpc";
import { ZCreateInputSchema } from "./create.schema";
import { ZDeleteInputSchema } from "./delete.schema";
import { ZDuplicateInputSchema } from "./duplicate.schema";
import { ZGetInputSchema } from "./get.schema";
import { ZEventTypeInputSchema } from "./getByViewer.schema";
import { get } from "./procedures/get";
import { ZUpdateInputSchema } from "./update.schema";
import { eventOwnerProcedure } from "./util";
@@ -101,21 +101,7 @@ export const eventTypesRouter = router({
});
}),
get: eventOwnerProcedure.input(ZGetInputSchema).query(async ({ ctx, input }) => {
if (!UNSTABLE_HANDLER_CACHE.get) {
UNSTABLE_HANDLER_CACHE.get = await import("./get.handler").then((mod) => mod.getHandler);
}
// Unreachable code but required for type safety
if (!UNSTABLE_HANDLER_CACHE.get) {
throw new Error("Failed to load handler");
}
return UNSTABLE_HANDLER_CACHE.get({
ctx,
input,
});
}),
get,
update: eventOwnerProcedure.input(ZUpdateInputSchema).mutation(async ({ ctx, input }) => {
if (!UNSTABLE_HANDLER_CACHE.update) {
@@ -0,0 +1,11 @@
import { ZGetInputSchema } from "../get.schema";
import { eventOwnerProcedure } from "../util";
export const get = eventOwnerProcedure.input(ZGetInputSchema).query(async ({ ctx, input }) => {
const handler = (await import("../get.handler")).getHandler;
return handler({
ctx,
input,
});
});
@@ -13,6 +13,7 @@ import { ZHasEditPermissionForUserSchema } from "./hasEditPermissionForUser.sche
import { ZInviteMemberInputSchema } from "./inviteMember/inviteMember.schema";
import { ZInviteMemberByTokenSchemaInputSchema } from "./inviteMemberByToken.schema";
import { ZListMembersInputSchema } from "./listMembers.schema";
import { hasTeamPlan } from "./procedures/hasTeamPlan";
import { ZPublishInputSchema } from "./publish.schema";
import { ZRemoveMemberInputSchema } from "./removeMember.schema";
import { ZResendInvitationInputSchema } from "./resendInvitation.schema";
@@ -111,10 +112,7 @@ export const viewerTeamsRouter = router({
const handler = await importHandler(namespaced("listMembers"), () => import("./listMembers.handler"));
return handler(opts);
}),
hasTeamPlan: authedProcedure.query(async (opts) => {
const handler = await importHandler(namespaced("hasTeamPlan"), () => import("./hasTeamPlan.handler"));
return handler(opts);
}),
hasTeamPlan,
listInvites: authedProcedure.query(async (opts) => {
const handler = await importHandler(namespaced("listInvites"), () => import("./listInvites.handler"));
return handler(opts);
@@ -0,0 +1,10 @@
import authedProcedure from "../../../../procedures/authedProcedure";
import { importHandler } from "../../../../trpc";
const NAMESPACE = "teams";
const namespaced = (s: string) => `${NAMESPACE}.${s}`;
export const hasTeamPlan = authedProcedure.query(async (opts) => {
const handler = await importHandler(namespaced("hasTeamPlan"), () => import("../hasTeamPlan.handler"));
return handler(opts);
});