first commit
This commit is contained in:
102
calcom/apps/web/server/lib/auth/login/getServerSideProps.tsx
Normal file
102
calcom/apps/web/server/lib/auth/login/getServerSideProps.tsx
Normal file
@@ -0,0 +1,102 @@
|
||||
import { jwtVerify } from "jose";
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
import { getCsrfToken } from "next-auth/react";
|
||||
|
||||
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
||||
import { isSAMLLoginEnabled, samlProductID, samlTenantID } from "@calcom/features/ee/sso/lib/saml";
|
||||
import { WEBSITE_URL } from "@calcom/lib/constants";
|
||||
import { getSafeRedirectUrl } from "@calcom/lib/getSafeRedirectUrl";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { IS_GOOGLE_LOGIN_ENABLED } from "@server/lib/constants";
|
||||
import { ssrInit } from "@server/lib/ssr";
|
||||
|
||||
export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||
const { req, res, query } = context;
|
||||
|
||||
const session = await getServerSession({ req, res });
|
||||
const ssr = await ssrInit(context);
|
||||
|
||||
const verifyJwt = (jwt: string) => {
|
||||
const secret = new TextEncoder().encode(process.env.CALENDSO_ENCRYPTION_KEY);
|
||||
|
||||
return jwtVerify(jwt, secret, {
|
||||
issuer: WEBSITE_URL,
|
||||
audience: `${WEBSITE_URL}/auth/login`,
|
||||
algorithms: ["HS256"],
|
||||
});
|
||||
};
|
||||
|
||||
let totpEmail = null;
|
||||
if (context.query.totp) {
|
||||
try {
|
||||
const decryptedJwt = await verifyJwt(context.query.totp as string);
|
||||
if (decryptedJwt.payload) {
|
||||
totpEmail = decryptedJwt.payload.email as string;
|
||||
} else {
|
||||
return {
|
||||
redirect: {
|
||||
destination: "/auth/error?error=JWT%20Invalid%20Payload",
|
||||
permanent: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
} catch (e) {
|
||||
return {
|
||||
redirect: {
|
||||
destination: "/auth/error?error=Invalid%20JWT%3A%20Please%20try%20again",
|
||||
permanent: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (session) {
|
||||
const { callbackUrl } = query;
|
||||
|
||||
if (callbackUrl) {
|
||||
try {
|
||||
const destination = getSafeRedirectUrl(callbackUrl as string);
|
||||
if (destination) {
|
||||
return {
|
||||
redirect: {
|
||||
destination,
|
||||
permanent: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
redirect: {
|
||||
destination: "/",
|
||||
permanent: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const userCount = await prisma.user.count();
|
||||
if (userCount === 0) {
|
||||
// Proceed to new onboarding to create first admin user
|
||||
return {
|
||||
redirect: {
|
||||
destination: "/auth/setup",
|
||||
permanent: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
return {
|
||||
props: {
|
||||
csrfToken: await getCsrfToken(context),
|
||||
trpcState: ssr.dehydrate(),
|
||||
isGoogleLoginEnabled: IS_GOOGLE_LOGIN_ENABLED,
|
||||
isSAMLLoginEnabled,
|
||||
samlTenantID,
|
||||
samlProductID,
|
||||
totpEmail,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
|
||||
import { ssrInit } from "@server/lib/ssr";
|
||||
|
||||
export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||
const ssr = await ssrInit(context);
|
||||
// Deleting old cookie manually, remove this code after all existing cookies have expired
|
||||
context.res?.setHeader(
|
||||
"Set-Cookie",
|
||||
"next-auth.session-token=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;"
|
||||
);
|
||||
|
||||
return {
|
||||
props: {
|
||||
trpcState: ssr.dehydrate(),
|
||||
query: context.query,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
import { getProviders, getCsrfToken } from "next-auth/react";
|
||||
|
||||
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
||||
|
||||
export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||
const { req } = context;
|
||||
|
||||
const session = await getServerSession({ req });
|
||||
const csrfToken = await getCsrfToken(context);
|
||||
const providers = await getProviders();
|
||||
if (session) {
|
||||
return {
|
||||
redirect: { destination: "/" },
|
||||
};
|
||||
}
|
||||
return {
|
||||
props: {
|
||||
csrfToken,
|
||||
providers,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
|
||||
import { getPremiumMonthlyPlanPriceId } from "@calcom/app-store/stripepayment/lib/utils";
|
||||
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
||||
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
|
||||
import stripe from "@calcom/features/ee/payments/server/stripe";
|
||||
import { hostedCal, isSAMLLoginEnabled, samlProductID, samlTenantID } from "@calcom/features/ee/sso/lib/saml";
|
||||
import { ssoTenantProduct } from "@calcom/features/ee/sso/lib/sso";
|
||||
import { IS_PREMIUM_USERNAME_ENABLED } from "@calcom/lib/constants";
|
||||
import { checkUsername } from "@calcom/lib/server/checkUsername";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { asStringOrNull } from "@lib/asStringOrNull";
|
||||
|
||||
import { ssrInit } from "@server/lib/ssr";
|
||||
|
||||
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
|
||||
// get query params and typecast them to string
|
||||
// (would be even better to assert them instead of typecasting)
|
||||
const providerParam = asStringOrNull(context.query.provider);
|
||||
const emailParam = asStringOrNull(context.query.email);
|
||||
const usernameParam = asStringOrNull(context.query.username);
|
||||
const successDestination = `/getting-started${usernameParam ? `?username=${usernameParam}` : ""}`;
|
||||
if (!providerParam) {
|
||||
throw new Error(`File is not named sso/[provider]`);
|
||||
}
|
||||
|
||||
const { req } = context;
|
||||
|
||||
const session = await getServerSession({ req });
|
||||
const ssr = await ssrInit(context);
|
||||
const { currentOrgDomain } = orgDomainConfig(context.req);
|
||||
|
||||
if (session) {
|
||||
// Validating if username is Premium, while this is true an email its required for stripe user confirmation
|
||||
if (usernameParam && session.user.email) {
|
||||
const availability = await checkUsername(usernameParam, currentOrgDomain);
|
||||
if (availability.available && availability.premium && IS_PREMIUM_USERNAME_ENABLED) {
|
||||
const stripePremiumUrl = await getStripePremiumUsernameUrl({
|
||||
userEmail: session.user.email,
|
||||
username: usernameParam,
|
||||
successDestination,
|
||||
});
|
||||
if (stripePremiumUrl) {
|
||||
return {
|
||||
redirect: {
|
||||
destination: stripePremiumUrl,
|
||||
permanent: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
redirect: {
|
||||
destination: successDestination,
|
||||
permanent: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
let error: string | null = null;
|
||||
|
||||
let tenant = samlTenantID;
|
||||
let product = samlProductID;
|
||||
|
||||
if (providerParam === "saml" && hostedCal) {
|
||||
if (!emailParam) {
|
||||
error = "Email not provided";
|
||||
} else {
|
||||
try {
|
||||
const ret = await ssoTenantProduct(prisma, emailParam);
|
||||
tenant = ret.tenant;
|
||||
product = ret.product;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
error = e.message;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return {
|
||||
redirect: {
|
||||
destination: `/auth/error?error=${error}`,
|
||||
permanent: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
trpcState: ssr.dehydrate(),
|
||||
provider: providerParam,
|
||||
isSAMLLoginEnabled,
|
||||
hostedCal,
|
||||
tenant,
|
||||
product,
|
||||
error,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
type GetStripePremiumUsernameUrl = {
|
||||
userEmail: string;
|
||||
username: string;
|
||||
successDestination: string;
|
||||
};
|
||||
|
||||
const getStripePremiumUsernameUrl = async ({
|
||||
userEmail,
|
||||
username,
|
||||
successDestination,
|
||||
}: GetStripePremiumUsernameUrl): Promise<string | null> => {
|
||||
// @TODO: probably want to check if stripe user email already exists? or not
|
||||
const customer = await stripe.customers.create({
|
||||
email: userEmail,
|
||||
metadata: {
|
||||
email: userEmail,
|
||||
username,
|
||||
},
|
||||
});
|
||||
|
||||
const checkoutSession = await stripe.checkout.sessions.create({
|
||||
mode: "subscription",
|
||||
payment_method_types: ["card"],
|
||||
customer: customer.id,
|
||||
line_items: [
|
||||
{
|
||||
price: getPremiumMonthlyPlanPriceId(),
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
success_url: `${process.env.NEXT_PUBLIC_WEBAPP_URL}${successDestination}&session_id={CHECKOUT_SESSION_ID}`,
|
||||
cancel_url: process.env.NEXT_PUBLIC_WEBAPP_URL || "https://app.cal.com",
|
||||
allow_promotion_codes: true,
|
||||
});
|
||||
|
||||
return checkoutSession.url;
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
import { samlProductID, samlTenantID } from "@calcom/features/ee/sso/lib/saml";
|
||||
|
||||
export async function getServerSideProps() {
|
||||
return {
|
||||
props: {
|
||||
samlTenantID,
|
||||
samlProductID,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
|
||||
export const getServerSideProps = async (_context: GetServerSidePropsContext) => {
|
||||
const EMAIL_FROM = process.env.EMAIL_FROM;
|
||||
|
||||
return {
|
||||
props: {
|
||||
EMAIL_FROM,
|
||||
},
|
||||
};
|
||||
};
|
||||
6
calcom/apps/web/server/lib/constants.ts
Normal file
6
calcom/apps/web/server/lib/constants.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export const GOOGLE_API_CREDENTIALS = process.env.GOOGLE_API_CREDENTIALS || "{}";
|
||||
export const { client_id: GOOGLE_CLIENT_ID, client_secret: GOOGLE_CLIENT_SECRET } =
|
||||
JSON.parse(GOOGLE_API_CREDENTIALS)?.web || {};
|
||||
export const GOOGLE_LOGIN_ENABLED = process.env.GOOGLE_LOGIN_ENABLED === "true";
|
||||
export const IS_GOOGLE_LOGIN_ENABLED = !!(GOOGLE_CLIENT_ID && GOOGLE_CLIENT_SECRET && GOOGLE_LOGIN_ENABLED);
|
||||
export const IS_SAML_LOGIN_ENABLED = !!(process.env.SAML_DATABASE_URL && process.env.SAML_ADMINS);
|
||||
@@ -0,0 +1,37 @@
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
import { getCsrfToken } from "next-auth/react";
|
||||
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
|
||||
|
||||
import { getLocale } from "@calcom/features/auth/lib/getLocale";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||
const id = context.params?.id as string;
|
||||
|
||||
let resetPasswordRequest = await prisma.resetPasswordRequest.findFirst({
|
||||
where: {
|
||||
id,
|
||||
expires: {
|
||||
gt: new Date(),
|
||||
},
|
||||
},
|
||||
select: {
|
||||
email: true,
|
||||
},
|
||||
});
|
||||
try {
|
||||
resetPasswordRequest &&
|
||||
(await prisma.user.findUniqueOrThrow({ where: { email: resetPasswordRequest.email } }));
|
||||
} catch (e) {
|
||||
resetPasswordRequest = null;
|
||||
}
|
||||
const locale = await getLocale(context.req);
|
||||
return {
|
||||
props: {
|
||||
isRequestExpired: !resetPasswordRequest,
|
||||
requestId: id,
|
||||
csrfToken: await getCsrfToken({ req: context.req }),
|
||||
...(await serverSideTranslations(locale, ["common"])),
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
import { getCsrfToken } from "next-auth/react";
|
||||
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
|
||||
|
||||
import { getLocale } from "@calcom/features/auth/lib/getLocale";
|
||||
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
||||
|
||||
export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||
const { req, res } = context;
|
||||
|
||||
const session = await getServerSession({ req });
|
||||
|
||||
// @TODO res will not be available in future pages (app dir)
|
||||
if (session) {
|
||||
res.writeHead(302, { Location: "/" });
|
||||
res.end();
|
||||
return { props: {} };
|
||||
}
|
||||
const locale = await getLocale(context.req);
|
||||
|
||||
return {
|
||||
props: {
|
||||
csrfToken: await getCsrfToken(context),
|
||||
...(await serverSideTranslations(locale, ["common"])),
|
||||
},
|
||||
};
|
||||
}
|
||||
22
calcom/apps/web/server/lib/getTranslations.ts
Normal file
22
calcom/apps/web/server/lib/getTranslations.ts
Normal 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,
|
||||
};
|
||||
}
|
||||
56
calcom/apps/web/server/lib/setup/getServerSideProps.tsx
Normal file
56
calcom/apps/web/server/lib/setup/getServerSideProps.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
|
||||
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
||||
import { getDeploymentKey } from "@calcom/features/ee/deployment/lib/getDeploymentKey";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { UserPermissionRole } from "@calcom/prisma/enums";
|
||||
|
||||
import { ssrInit } from "@server/lib/ssr";
|
||||
|
||||
export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||
const { req } = context;
|
||||
|
||||
const ssr = await ssrInit(context);
|
||||
const userCount = await prisma.user.count();
|
||||
|
||||
const session = await getServerSession({ req });
|
||||
|
||||
if (session?.user.role && session?.user.role !== UserPermissionRole.ADMIN) {
|
||||
return {
|
||||
redirect: {
|
||||
destination: `/404`,
|
||||
permanent: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const deploymentKey = await prisma.deployment.findUnique({
|
||||
where: { id: 1 },
|
||||
select: { licenseKey: true },
|
||||
});
|
||||
|
||||
// Check existant CALCOM_LICENSE_KEY env var and acccount for it
|
||||
if (!!process.env.CALCOM_LICENSE_KEY && !deploymentKey?.licenseKey) {
|
||||
await prisma.deployment.upsert({
|
||||
where: { id: 1 },
|
||||
update: {
|
||||
licenseKey: process.env.CALCOM_LICENSE_KEY,
|
||||
agreedLicenseAt: new Date(),
|
||||
},
|
||||
create: {
|
||||
licenseKey: process.env.CALCOM_LICENSE_KEY,
|
||||
agreedLicenseAt: new Date(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const isFreeLicense = (await getDeploymentKey(prisma)) === "";
|
||||
|
||||
return {
|
||||
props: {
|
||||
trpcState: ssr.dehydrate(),
|
||||
isFreeLicense,
|
||||
userCount,
|
||||
},
|
||||
};
|
||||
}
|
||||
51
calcom/apps/web/server/lib/ssg.ts
Normal file
51
calcom/apps/web/server/lib/ssg.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import type { GetStaticPropsContext } from "next";
|
||||
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
|
||||
import superjson from "superjson";
|
||||
|
||||
import { CALCOM_VERSION } from "@calcom/lib/constants";
|
||||
import prisma, { readonlyPrisma } from "@calcom/prisma";
|
||||
import { createServerSideHelpers } from "@calcom/trpc/react/server";
|
||||
import { appRouter } from "@calcom/trpc/server/routers/_app";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const { i18n } = require("@calcom/config/next-i18next.config");
|
||||
|
||||
/**
|
||||
* Initialize static site rendering tRPC helpers.
|
||||
* Provides a method to prefetch tRPC-queries in a `getStaticProps`-function.
|
||||
* Automatically prefetches i18n based on the passed in `context`-object to prevent i18n-flickering.
|
||||
* Make sure to `return { props: { trpcState: ssr.dehydrate() } }` at the end.
|
||||
*/
|
||||
export async function ssgInit<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"]);
|
||||
|
||||
const ssg = createServerSideHelpers({
|
||||
router: appRouter,
|
||||
transformer: superjson,
|
||||
ctx: {
|
||||
prisma,
|
||||
insightsDb: readonlyPrisma,
|
||||
session: null,
|
||||
locale,
|
||||
i18n: _i18n,
|
||||
},
|
||||
});
|
||||
|
||||
// i18n translations are already retrieved from serverSideTranslations call, there is no need to run a i18n.fetch
|
||||
// we can set query data directly to the queryClient
|
||||
const queryKey = [
|
||||
["viewer", "public", "i18n"],
|
||||
{ input: { locale, CalComVersion: CALCOM_VERSION }, type: "query" },
|
||||
];
|
||||
|
||||
ssg.queryClient.setQueryData(queryKey, { i18n: _i18n });
|
||||
|
||||
return ssg;
|
||||
}
|
||||
88
calcom/apps/web/server/lib/ssr.ts
Normal file
88
calcom/apps/web/server/lib/ssr.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
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 { createServerSideHelpers } from "@calcom/trpc/react/server";
|
||||
import { createContext } from "@calcom/trpc/server/createContext";
|
||||
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.
|
||||
* Provides a method to prefetch tRPC-queries in a `getServerSideProps`-function.
|
||||
* Automatically prefetches i18n based on the passed in `context`-object to prevent i18n-flickering.
|
||||
* Make sure to `return { props: { trpcState: ssr.dehydrate() } }` at the end.
|
||||
*/
|
||||
export async function ssrInit(context: GetServerSidePropsContext, options?: { noI18nPreload: boolean }) {
|
||||
const ctx = await createContext(context);
|
||||
const locale = await getLocale(context.req);
|
||||
const i18n = await serverSideTranslations(locale, ["common", "vital"]);
|
||||
|
||||
const ssr = createServerSideHelpers({
|
||||
router: routerSlice,
|
||||
transformer: superjson,
|
||||
ctx: { ...ctx, locale, i18n },
|
||||
});
|
||||
|
||||
// i18n translations are already retrieved from serverSideTranslations call, there is no need to run a i18n.fetch
|
||||
// we can set query data directly to the queryClient
|
||||
const queryKey = [
|
||||
["viewer", "public", "i18n"],
|
||||
{ input: { locale, CalComVersion: CALCOM_VERSION }, type: "query" },
|
||||
];
|
||||
if (!options?.noI18nPreload) {
|
||||
ssr.queryClient.setQueryData(queryKey, { i18n });
|
||||
}
|
||||
|
||||
await Promise.allSettled([
|
||||
// So feature flags are available on first render
|
||||
ssr.viewer.features.map.prefetch(),
|
||||
// Provides a better UX to the users who have already upgraded.
|
||||
ssr.viewer.teams.hasTeamPlan.prefetch(),
|
||||
ssr.viewer.public.session.prefetch(),
|
||||
ssr.viewer.me.prefetch(),
|
||||
]);
|
||||
|
||||
return ssr;
|
||||
}
|
||||
Reference in New Issue
Block a user