Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: makes production build ready for docker #12686

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/api/lib/helpers/customPrisma.ts
Expand Up @@ -28,8 +28,8 @@ export const customPrismaClient: NextMiddleware = async (req, res, next) => {
}
req.prisma = customPrisma({ datasources: { db: { url: databaseUrl } } });
/* @note:
In order to skip verifyApiKey for customPrisma requests,
we pass isAdmin true, and userId 0, if we detect them later,
In order to skip verifyApiKey for customPrisma requests,
we pass isAdmin true, and userId 0, if we detect them later,
we skip verifyApiKey logic and pass onto next middleware instead.
*/
req.isAdmin = true;
Expand Down
85 changes: 85 additions & 0 deletions apps/web/app-config.ts
@@ -0,0 +1,85 @@
import getConfig from "next/config";

function getPublicVariables(env: NodeJS.ProcessEnv): Partial<NodeJS.ProcessEnv> {
if (!env) {
return {};
}

const variables = Object.keys(env)
.filter((key) => key.startsWith("NEXT_PUBLIC_"))
.reduce((vars: Partial<NodeJS.ProcessEnv>, key: string) => {
vars[key] = env[key];
return vars;
}, {});

return variables;
}

const publicRuntimeConfig = {
...getPublicVariables(process.env),
...((getConfig() && getConfig().publicRuntimeConfig) || {}),
};

const {
NEXT_PUBLIC_WEBAPP_URL,
NEXT_PUBLIC_WEBSITE_URL,
NEXT_PUBLIC_APP_NAME,
NEXT_PUBLIC_SUPPORT_MAIL_ADDRESS,
NEXT_PUBLIC_COMPANY_NAME,
NEXT_PUBLIC_SENDER_ID,
NEXT_PUBLIC_SENDGRID_SENDER_NAME,
NEXT_PUBLIC_IS_E2E,
NEXT_PUBLIC_STRIPE_PREMIUM_PLAN_PRICE_MONTHLY,
NEXT_PUBLIC_SENTRY_DSN,
NEXT_PUBLIC_DEBUG,
NEXT_PUBLIC_DISABLE_SIGNUP,
NEXT_PUBLIC_HOSTED_CAL_FEATURES,
NEXT_PUBLIC_STRIPE_PUBLIC_KEY,
NEXT_PUBLIC_CALCOM_VERSION,
NEXT_PUBLIC_VERCEL_URL,
NEXT_PUBLIC_EMBED_LIB_URL,
NEXT_PUBLIC_MINUTES_TO_BOOK,
NEXT_PUBLIC_AVAILABILITY_SCHEDULE_INTERVAL,
NEXT_PUBLIC_FRESHCHAT_HOST,
NEXT_PUBLIC_FRESHCHAT_TOKEN,
NEXT_PUBLIC_HELPSCOUT_KEY,
NEXT_PUBLIC_INTERCOM_APP_ID,
NEXT_PUBLIC_ZENDESK_KEY,
NEXT_PUBLIC_STRIPE_PREMIUM_PLAN_PRODUCT_ID,
NEXT_PUBLIC_STRIPE_TEAM_MONTHLY_PRICE_ID,
NEXT_PUBLIC_TEAM_IMPERSONATION,
NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA,
} = publicRuntimeConfig;

export const AppConfig = {
env: {
NEXT_PUBLIC_WEBAPP_URL: String(NEXT_PUBLIC_WEBAPP_URL),
NEXT_PUBLIC_WEBSITE_URL: String(NEXT_PUBLIC_WEBSITE_URL),
NEXT_PUBLIC_APP_NAME,
NEXT_PUBLIC_SUPPORT_MAIL_ADDRESS,
NEXT_PUBLIC_COMPANY_NAME,
NEXT_PUBLIC_SENDER_ID,
NEXT_PUBLIC_SENDGRID_SENDER_NAME,
NEXT_PUBLIC_IS_E2E,
NEXT_PUBLIC_STRIPE_PREMIUM_PLAN_PRICE_MONTHLY,
NEXT_PUBLIC_SENTRY_DSN,
NEXT_PUBLIC_DEBUG,
NEXT_PUBLIC_DISABLE_SIGNUP,
NEXT_PUBLIC_HOSTED_CAL_FEATURES,
NEXT_PUBLIC_STRIPE_PUBLIC_KEY,
NEXT_PUBLIC_CALCOM_VERSION,
NEXT_PUBLIC_VERCEL_URL,
NEXT_PUBLIC_EMBED_LIB_URL,
NEXT_PUBLIC_MINUTES_TO_BOOK,
NEXT_PUBLIC_AVAILABILITY_SCHEDULE_INTERVAL,
NEXT_PUBLIC_FRESHCHAT_HOST,
NEXT_PUBLIC_FRESHCHAT_TOKEN,
NEXT_PUBLIC_HELPSCOUT_KEY,
NEXT_PUBLIC_INTERCOM_APP_ID,
NEXT_PUBLIC_ZENDESK_KEY,
NEXT_PUBLIC_STRIPE_PREMIUM_PLAN_PRODUCT_ID,
NEXT_PUBLIC_STRIPE_TEAM_MONTHLY_PRICE_ID,
NEXT_PUBLIC_TEAM_IMPERSONATION,
NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA,
},
};
6 changes: 4 additions & 2 deletions apps/web/app/_trpc/trpc-provider.tsx
Expand Up @@ -9,6 +9,7 @@ import { httpLink } from "@calcom/trpc/client/links/httpLink";
import { loggerLink } from "@calcom/trpc/client/links/loggerLink";
import { splitLink } from "@calcom/trpc/client/links/splitLink";
import { ENDPOINTS } from "@calcom/trpc/react/shared";
import { AppConfig } from "@calcom/web/app-config";

export type Endpoint = (typeof ENDPOINTS)[number];

Expand Down Expand Up @@ -45,20 +46,21 @@ export const TrpcProvider: React.FC<{ children: React.ReactNode; dehydratedState
defaultOptions: { queries: { staleTime: 5000 } },
})
);

const url =
typeof window !== "undefined"
? "/api/trpc"
: process.env.VERCEL_URL
? `https://${process.env.VERCEL_URL}/api/trpc`
: `${process.env.NEXT_PUBLIC_WEBAPP_URL}/api/trpc`;
: `${AppConfig.env.NEXT_PUBLIC_WEBAPP_URL}/api/trpc`;

const [trpcClient] = useState(() =>
trpc.createClient({
links: [
// adds pretty logs to your console in development and logs errors in production
loggerLink({
enabled: (opts) =>
!!process.env.NEXT_PUBLIC_DEBUG || (opts.direction === "down" && opts.result instanceof Error),
!!AppConfig.env.NEXT_PUBLIC_DEBUG || (opts.direction === "down" && opts.result instanceof Error),
}),
splitLink({
// check for context property `skipBatch`
Expand Down
5 changes: 3 additions & 2 deletions apps/web/components/setup/AdminUser.tsx
Expand Up @@ -10,6 +10,7 @@ import { WEBSITE_URL } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { EmailField, EmptyScreen, Label, PasswordField, TextField } from "@calcom/ui";
import { UserCheck } from "@calcom/ui/components/icon";
import { AppConfig } from "@calcom/web/app-config";

export const AdminUserContainer = (props: React.ComponentProps<typeof AdminUser> & { userCount: number }) => {
const { t } = useLocale();
Expand Down Expand Up @@ -110,15 +111,15 @@ export const AdminUser = (props: { onSubmit: () => void; onError: () => void; on
<span className="block">{t("username")}</span>
{longWebsiteUrl && (
<small className="items-centerpx-3 bg-subtle border-default text-subtle mt-2 inline-flex rounded-t-md border border-b-0 px-3 py-1">
{process.env.NEXT_PUBLIC_WEBSITE_URL}
{AppConfig.env.NEXT_PUBLIC_WEBSITE_URL}
</small>
)}
</Label>
<TextField
addOnLeading={
!longWebsiteUrl && (
<span className="text-subtle inline-flex items-center rounded-none px-3 text-sm">
{process.env.NEXT_PUBLIC_WEBSITE_URL}/
{AppConfig.env.NEXT_PUBLIC_WEBSITE_URL}/
</span>
)
}
Expand Down
Expand Up @@ -17,6 +17,7 @@ import { trpc } from "@calcom/trpc/react";
import type { AppRouter } from "@calcom/trpc/server/routers/_app";
import { Button, Dialog, DialogClose, DialogContent, DialogFooter, Input, Label } from "@calcom/ui";
import { Check, Edit2, ExternalLink, Star as StarSolid } from "@calcom/ui/components/icon";
import { AppConfig } from "@calcom/web/app-config";

export enum UsernameChangeStatusEnum {
UPGRADE = "UPGRADE",
Expand Down Expand Up @@ -197,7 +198,7 @@ const PremiumTextfield = (props: ICustomUsernameProps) => {
isInputUsernamePremium ? "border border-orange-400 " : "",
"border-default bg-muted text-subtle hidden h-9 items-center rounded-l-md border border-r-0 px-3 text-sm md:inline-flex"
)}>
{process.env.NEXT_PUBLIC_WEBSITE_URL.replace("https://", "").replace("http://", "")}/
{AppConfig.env.NEXT_PUBLIC_WEBSITE_URL?.replace("https://", "").replace("http://", "")}/
</span>

<div className="relative w-full">
Expand Down
28 changes: 28 additions & 0 deletions apps/web/next.config.js
Expand Up @@ -154,6 +154,34 @@ const matcherConfigUserTypeEmbedRoute = {

/** @type {import("next").NextConfig} */
const nextConfig = {
publicRuntimeConfig: {
NEXT_PUBLIC_WEBAPP_URL: process.env.NEXT_PUBLIC_WEBAPP_URL,
NEXT_PUBLIC_SENTRY_DSN: process.env.NEXT_PUBLIC_SENTRY_DSN,
NEXT_PUBLIC_WEBSITE_URL: process.env.NEXT_PUBLIC_WEBSITE_URL,
NEXT_PUBLIC_APP_NAME: process.env.NEXT_PUBLIC_APP_NAME,
NEXT_PUBLIC_SUPPORT_MAIL_ADDRESS: process.env.NEXT_PUBLIC_SUPPORT_MAIL_ADDRESS,
NEXT_PUBLIC_COMPANY_NAME: process.env.NEXT_PUBLIC_COMPANY_NAME,
NEXT_PUBLIC_SENDER_ID: process.env.NEXT_PUBLIC_SENDER_ID,
NEXT_PUBLIC_SENDGRID_SENDER_NAME: process.env.NEXT_PUBLIC_SENDGRID_SENDER_NAME,
NEXT_PUBLIC_IS_E2E: process.env.NEXT_PUBLIC_IS_E2E,
NEXT_PUBLIC_STRIPE_PREMIUM_PLAN_PRICE_MONTHLY: process.env.NEXT_PUBLIC_STRIPE_PREMIUM_PLAN_PRICE_MONTHLY,
NEXT_PUBLIC_DEBUG: process.env.NEXT_PUBLIC_DEBUG,
NEXT_PUBLIC_DISABLE_SIGNUP: process.env.NEXT_PUBLIC_DISABLE_SIGNUP,
NEXT_PUBLIC_HOSTED_CAL_FEATURES: process.env.NEXT_PUBLIC_HOSTED_CAL_FEATURES,
NEXT_PUBLIC_STRIPE_PUBLIC_KEY: process.env.NEXT_PUBLIC_STRIPE_PUBLIC_KEY,
NEXT_PUBLIC_CALCOM_VERSION: process.env.NEXT_PUBLIC_CALCOM_VERSION,
NEXT_PUBLIC_VERCEL_URL: process.env.NEXT_PUBLIC_VERCEL_URL,
NEXT_PUBLIC_EMBED_LIB_URL: process.env.NEXT_PUBLIC_EMBED_LIB_URL,
NEXT_PUBLIC_MINUTES_TO_BOOK: process.env.NEXT_PUBLIC_MINUTES_TO_BOOK,
NEXT_PUBLIC_AVAILABILITY_SCHEDULE_INTERVAL: process.env.NEXT_PUBLIC_AVAILABILITY_SCHEDULE_INTERVAL,
NEXT_PUBLIC_FRESHCHAT_HOST: process.env.NEXT_PUBLIC_FRESHCHAT_HOST,
NEXT_PUBLIC_FRESHCHAT_TOKEN: process.env.NEXT_PUBLIC_FRESHCHAT_TOKEN,
NEXT_PUBLIC_HELPSCOUT_KEY: process.env.NEXT_PUBLIC_HELPSCOUT_KEY,
NEXT_PUBLIC_INTERCOM_APP_ID: process.env.NEXT_PUBLIC_INTERCOM_APP_ID,
NEXT_PUBLIC_ZENDESK_KEY: process.env.NEXT_PUBLIC_ZENDESK_KEY,
NEXT_PUBLIC_TEAM_IMPERSONATION: process.env.NEXT_PUBLIC_TEAM_IMPERSONATION,
NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA: process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA,
},
i18n: {
...i18n,
localeDetection: false,
Expand Down
3 changes: 2 additions & 1 deletion apps/web/pages/404.tsx
Expand Up @@ -12,6 +12,7 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
import { HeadSeo } from "@calcom/ui";
import { BookOpen, Check, ChevronRight, FileText, Shield } from "@calcom/ui/components/icon";
import { Discord } from "@calcom/ui/components/icon/Discord";
import { AppConfig } from "@calcom/web/app-config";

import PageWrapper from "@components/PageWrapper";

Expand Down Expand Up @@ -138,7 +139,7 @@ export default function Custom404() {
/>
<div className="bg-default min-h-screen px-4" data-testid="404-page">
<main className="mx-auto max-w-xl pb-6 pt-16 sm:pt-24">
{isSignup && process.env.NEXT_PUBLIC_WEBAPP_URL !== "https://app.cal.com" ? (
{isSignup && AppConfig.env.NEXT_PUBLIC_WEBAPP_URL !== "https://app.cal.com" ? (
<div>
<div>
<p className="text-emphasis text-sm font-semibold uppercase tracking-wide">
Expand Down
3 changes: 2 additions & 1 deletion apps/web/pages/api/auth/signup.ts
Expand Up @@ -7,6 +7,7 @@ import { IS_PREMIUM_USERNAME_ENABLED } from "@calcom/lib/constants";
import { HttpError } from "@calcom/lib/http-error";
import logger from "@calcom/lib/logger";
import { signupSchema } from "@calcom/prisma/zod-utils";
import { AppConfig } from "@calcom/web/app-config";

function ensureSignupIsEnabled(req: RequestWithUsernameStatus) {
const { token } = signupSchema
Expand All @@ -18,7 +19,7 @@ function ensureSignupIsEnabled(req: RequestWithUsernameStatus) {
// Stil allow signups if there is a team invite
if (token) return;

if (process.env.NEXT_PUBLIC_DISABLE_SIGNUP === "true") {
if (AppConfig.env.NEXT_PUBLIC_DISABLE_SIGNUP === "true") {
throw new HttpError({
statusCode: 403,
message: "Signup is disabled",
Expand Down
6 changes: 4 additions & 2 deletions apps/web/pages/auth/login.tsx
Expand Up @@ -14,7 +14,8 @@ import { SAMLLogin } from "@calcom/features/auth/SAMLLogin";
import { ErrorCode } from "@calcom/features/auth/lib/ErrorCode";
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
import { isSAMLLoginEnabled, samlProductID, samlTenantID } from "@calcom/features/ee/sso/lib/saml";
import { WEBAPP_URL, WEBSITE_URL, HOSTED_CAL_FEATURES } from "@calcom/lib/constants";
import { WEBSITE_URL, HOSTED_CAL_FEATURES } from "@calcom/lib/constants";
import { WEBAPP_URL } from "@calcom/lib/constants";
import { getSafeRedirectUrl } from "@calcom/lib/getSafeRedirectUrl";
import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams";
import { useLocale } from "@calcom/lib/hooks/useLocale";
Expand All @@ -23,6 +24,7 @@ import prisma from "@calcom/prisma";
import { trpc } from "@calcom/trpc/react";
import { Alert, Button, EmailField, PasswordField } from "@calcom/ui";
import { ArrowLeft, Lock } from "@calcom/ui/components/icon";
import { AppConfig } from "@calcom/web/app-config";

import type { inferSSRProps } from "@lib/types/inferSSRProps";
import type { WithNonceProps } from "@lib/withNonce";
Expand Down Expand Up @@ -184,7 +186,7 @@ inferSSRProps<typeof _getServerSideProps> & WithNonceProps<{}>) {
? !totpEmail
? TwoFactorFooter
: ExternalTotpFooter
: process.env.NEXT_PUBLIC_DISABLE_SIGNUP !== "true"
: AppConfig.env.NEXT_PUBLIC_DISABLE_SIGNUP !== "true"
? LoginFooter
: null
}>
Expand Down
4 changes: 3 additions & 1 deletion apps/web/pages/auth/new.tsx
@@ -1,6 +1,8 @@
import { AppConfig } from "@calcom/web/app-config";

export default function NewUserPage() {
if (typeof window !== "undefined") {
window.location.assign(process.env.NEXT_PUBLIC_WEBAPP_URL || "https://app.cal.com");
window.location.assign(AppConfig.env.NEXT_PUBLIC_WEBAPP_URL || "https://app.cal.com");
}
return null;
}
5 changes: 3 additions & 2 deletions apps/web/pages/auth/sso/[provider].tsx
Expand Up @@ -13,6 +13,7 @@ import { IS_PREMIUM_USERNAME_ENABLED } from "@calcom/lib/constants";
import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams";
import { checkUsername } from "@calcom/lib/server/checkUsername";
import prisma from "@calcom/prisma";
import { AppConfig } from "@calcom/web/app-config";

import { asStringOrNull } from "@lib/asStringOrNull";
import type { inferSSRProps } from "@lib/types/inferSSRProps";
Expand Down Expand Up @@ -171,8 +172,8 @@ const getStripePremiumUsernameUrl = async ({
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",
success_url: `${AppConfig.env.NEXT_PUBLIC_WEBAPP_URL}${successDestination}&session_id={CHECKOUT_SESSION_ID}`,
cancel_url: AppConfig.env.NEXT_PUBLIC_WEBAPP_URL || "https://app.cal.com",
allow_promotion_codes: true,
});

Expand Down
3 changes: 2 additions & 1 deletion apps/web/pages/settings/admin/impersonation.tsx
Expand Up @@ -5,6 +5,7 @@ import { useRef } from "react";

import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Button, Meta, TextField } from "@calcom/ui";
import { AppConfig } from "@calcom/web/app-config";

import PageWrapper from "@components/PageWrapper";
import { getLayout } from "@components/auth/layouts/AdminLayout";
Expand All @@ -27,7 +28,7 @@ function AdminView() {
<TextField
containerClassName="w-full"
name={t("user_impersonation_heading")}
addOnLeading={<>{process.env.NEXT_PUBLIC_WEBSITE_URL}/</>}
addOnLeading={<>{AppConfig.env.NEXT_PUBLIC_WEBSITE_URL}/</>}
ref={usernameRef}
hint={t("impersonate_user_tip")}
defaultValue={undefined}
Expand Down
3 changes: 2 additions & 1 deletion apps/web/pages/settings/my-account/profile.tsx
Expand Up @@ -42,6 +42,7 @@ import {
TextField,
} from "@calcom/ui";
import { AlertTriangle, Trash2 } from "@calcom/ui/components/icon";
import { AppConfig } from "@calcom/web/app-config";

import PageWrapper from "@components/PageWrapper";
import TwoFactor from "@components/auth/TwoFactor";
Expand Down Expand Up @@ -127,7 +128,7 @@ const ProfileView = () => {
showToast(t("Your account was deleted"), "success");

setHasDeleteErrors(false); // dismiss any open errors
if (process.env.NEXT_PUBLIC_WEBAPP_URL === "https://app.cal.com") {
if (AppConfig.env.NEXT_PUBLIC_WEBAPP_URL === "https://app.cal.com") {
signOut({ callbackUrl: "/auth/logout?survey=true" });
} else {
signOut({ callbackUrl: "/auth/logout" });
Expand Down
9 changes: 5 additions & 4 deletions apps/web/pages/signup.tsx
Expand Up @@ -28,6 +28,7 @@ import { teamMetadataSchema } from "@calcom/prisma/zod-utils";
import { signupSchema as apiSignupSchema } from "@calcom/prisma/zod-utils";
import type { inferSSRProps } from "@calcom/types/inferSSRProps";
import { Button, HeadSeo, PasswordField, TextField, Form, Alert } from "@calcom/ui";
import { AppConfig } from "@calcom/web/app-config";

import PageWrapper from "@components/PageWrapper";

Expand Down Expand Up @@ -287,7 +288,7 @@ export default function Signup({
addOnLeading={
orgSlug
? `${getOrgFullOrigin(orgSlug, { protocol: true })}/`
: `${process.env.NEXT_PUBLIC_WEBSITE_URL}/`
: `${AppConfig.env.NEXT_PUBLIC_WEBSITE_URL}/`
}
/>
{/* Email */}
Expand Down Expand Up @@ -361,7 +362,7 @@ export default function Signup({
onClick={async () => {
setIsGoogleLoading(true);
const username = formMethods.getValues("username");
const baseUrl = process.env.NEXT_PUBLIC_WEBAPP_URL;
const baseUrl = AppConfig.env.NEXT_PUBLIC_WEBAPP_URL;
const GOOGLE_AUTH_URL = `${baseUrl}/auth/sso/google`;
if (username) {
// If username is present we save it in query params to check for premium
Expand Down Expand Up @@ -408,7 +409,7 @@ export default function Signup({
sp.set("username", formMethods.getValues("username"));
sp.set("email", formMethods.getValues("email"));
router.push(
`${process.env.NEXT_PUBLIC_WEBAPP_URL}/auth/sso/saml` + `?${sp.toString()}`
`${AppConfig.env.NEXT_PUBLIC_WEBAPP_URL}/auth/sso/saml` + `?${sp.toString()}`
);
}}>
<ShieldCheckIcon className="mr-2 h-5 w-5" />
Expand Down Expand Up @@ -519,7 +520,7 @@ export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
// username + email prepopulated from query params
const { username: preFillusername, email: prefilEmail } = querySchema.parse(ctx.query);

if ((process.env.NEXT_PUBLIC_DISABLE_SIGNUP === "true" && !token) || flags["disable-signup"]) {
if ((AppConfig.env.NEXT_PUBLIC_DISABLE_SIGNUP === "true" && !token) || flags["disable-signup"]) {
return {
notFound: true,
};
Expand Down
2 changes: 1 addition & 1 deletion apps/web/playwright/change-username.e2e.ts
@@ -1,8 +1,8 @@
import { expect } from "@playwright/test";

import stripe from "@calcom/features/ee/payments/server/stripe";
import { WEBAPP_URL } from "@calcom/lib/constants";

import { WEBAPP_URL } from "./constants";
import { test } from "./lib/fixtures";

test.describe.configure({ mode: "parallel" });
Expand Down