mirror of
https://github.com/formbricks/formbricks.git
synced 2026-03-03 01:24:59 -06:00
Add support for Next.js Server-Components (#272)
* Add new env variable NEXT_PUBLIC_WEBAPP_URL that is used server-side for the current address * Move Next-Auth to App-Directory * Move Membership-API & User-API to App-Directory * Update env-examples with new structure
This commit is contained in:
28
.env.docker
28
.env.docker
@@ -4,20 +4,40 @@
|
||||
|
||||
|
||||
############
|
||||
# Basics #
|
||||
# BASICS #
|
||||
############
|
||||
|
||||
NEXT_PUBLIC_WEBAPP_URL=http://localhost:3000
|
||||
|
||||
##############
|
||||
# DATABASE #
|
||||
##############
|
||||
|
||||
DATABASE_URL='postgresql://postgres:postgres@postgres:5432/formbricks?schema=public'
|
||||
|
||||
# Uncomment to enable a dedicated connection pool for Prisma using Prisma Data Proxy
|
||||
# Cold boots will be faster and you'll be able to scale your DB independently of your app.
|
||||
# @see https://www.prisma.io/docs/data-platform/data-proxy/use-data-proxy
|
||||
# PRISMA_GENERATE_DATAPROXY=true
|
||||
PRISMA_GENERATE_DATAPROXY=
|
||||
|
||||
###############
|
||||
# NEXT AUTH #
|
||||
###############
|
||||
|
||||
# @see: https://next-auth.js.org/configuration/options#nextauth_secret
|
||||
# You can use: `openssl rand -base64 32` to generate one
|
||||
NEXTAUTH_SECRET=RANDOM_STRING
|
||||
|
||||
# Set this to your public-facing URL, e.g., https://example.com
|
||||
# You do not need the NEXTAUTH_URL environment variable in Vercel.
|
||||
NEXTAUTH_URL=http://localhost:3000
|
||||
|
||||
# If you encounter NEXT_AUTH URL problems this should always be localhost:3000 (or whatever port your app is running on)
|
||||
# NEXTAUTH_URL_INTERNAL=http://localhost:3000
|
||||
|
||||
DATABASE_URL='postgresql://postgres:postgres@postgres:5432/postgres?schema=public'
|
||||
|
||||
################
|
||||
# Mail Setup #
|
||||
# MAIL SETUP #
|
||||
################
|
||||
|
||||
# Necessary if email verification and password reset are enabled.
|
||||
|
||||
31
.env.example
31
.env.example
@@ -4,18 +4,16 @@
|
||||
|
||||
|
||||
############
|
||||
# Basics #
|
||||
# BASICS #
|
||||
############
|
||||
|
||||
NEXTAUTH_SECRET=RANDOM_STRING
|
||||
NEXT_PUBLIC_WEBAPP_URL=http://localhost:3000
|
||||
|
||||
# Set this to your public-facing URL, e.g., https://example.com
|
||||
NEXTAUTH_URL=http://localhost:3000
|
||||
##############
|
||||
# DATABASE #
|
||||
##############
|
||||
|
||||
# If you encounter NEXT_AUTH URL problems this should always be localhost:3000 (or whatever port your app is running on)
|
||||
# NEXTAUTH_URL_INTERNAL=http://localhost:3000
|
||||
|
||||
DATABASE_URL='postgresql://postgres:postgres@localhost:5432/postgres?schema=public'
|
||||
DATABASE_URL='postgresql://postgres:postgres@localhost:5432/formbricks?schema=public'
|
||||
|
||||
# Uncomment to enable a dedicated connection pool for Prisma using Prisma Data Proxy
|
||||
# Cold boots will be faster and you'll be able to scale your DB independently of your app.
|
||||
@@ -23,8 +21,23 @@ DATABASE_URL='postgresql://postgres:postgres@localhost:5432/postgres?schema=publ
|
||||
# PRISMA_GENERATE_DATAPROXY=true
|
||||
PRISMA_GENERATE_DATAPROXY=
|
||||
|
||||
###############
|
||||
# NEXT AUTH #
|
||||
###############
|
||||
|
||||
# @see: https://next-auth.js.org/configuration/options#nextauth_secret
|
||||
# You can use: `openssl rand -base64 32` to generate one
|
||||
NEXTAUTH_SECRET=RANDOM_STRING
|
||||
|
||||
# Set this to your public-facing URL, e.g., https://example.com
|
||||
# You do not need the NEXTAUTH_URL environment variable in Vercel.
|
||||
NEXTAUTH_URL=http://localhost:3000
|
||||
|
||||
# If you encounter NEXT_AUTH URL problems this should always be localhost:3000 (or whatever port your app is running on)
|
||||
# NEXTAUTH_URL_INTERNAL=http://localhost:3000
|
||||
|
||||
################
|
||||
# Mail Setup #
|
||||
# MAIL SETUP #
|
||||
################
|
||||
|
||||
# Necessary if email verification and password reset are enabled.
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import LoadingSpinner from "@/components/shared/LoadingSpinner";
|
||||
import { fetcher } from "@formbricks/lib/fetcher";
|
||||
import type { Session } from "next-auth";
|
||||
import { signOut } from "next-auth/react";
|
||||
import { redirect } from "next/navigation";
|
||||
import { useEffect } from "react";
|
||||
import useSWR from "swr";
|
||||
|
||||
interface HomeRedirectProps {
|
||||
session: Session;
|
||||
}
|
||||
|
||||
export function HomeRedirect({ session }: HomeRedirectProps) {
|
||||
const { data, error } = useSWR(`/api/v1/environments/find-first`, fetcher);
|
||||
|
||||
useEffect(() => {
|
||||
if (session) {
|
||||
if (!session.user?.onboardingDisplayed) {
|
||||
return redirect(`/onboarding`);
|
||||
}
|
||||
|
||||
if (data && !error) {
|
||||
return redirect(`/environments/${data.id}`);
|
||||
} else if (error) {
|
||||
console.error(error);
|
||||
}
|
||||
} else {
|
||||
return redirect(`/auth/login`);
|
||||
}
|
||||
}, [data, error, session]);
|
||||
|
||||
if (error) {
|
||||
setTimeout(() => {
|
||||
signOut();
|
||||
}, 3000);
|
||||
return <div>There was an error with your current Session. You are getting redirected to the login.</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<LoadingSpinner />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -2,9 +2,7 @@ import { verifyPassword } from "@/lib/auth";
|
||||
import { verifyToken } from "@/lib/jwt";
|
||||
import { prisma } from "@formbricks/database";
|
||||
import { IdentityProvider } from "@prisma/client";
|
||||
import { NextApiRequest, NextApiResponse } from "next";
|
||||
import type { NextAuthOptions } from "next-auth";
|
||||
import NextAuth from "next-auth";
|
||||
import CredentialsProvider from "next-auth/providers/credentials";
|
||||
import GitHubProvider from "next-auth/providers/github";
|
||||
|
||||
@@ -350,7 +348,3 @@ export const authOptions: NextAuthOptions = {
|
||||
error: "/auth/login", // Error code passed in query string as ?error=
|
||||
},
|
||||
};
|
||||
|
||||
export default async function auth(req: NextApiRequest, res: NextApiResponse) {
|
||||
return await NextAuth(req, res, authOptions);
|
||||
}
|
||||
6
apps/web/app/api/auth/[...nextauth]/route.ts
Normal file
6
apps/web/app/api/auth/[...nextauth]/route.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import NextAuth from "next-auth";
|
||||
import { authOptions } from "./authOptions";
|
||||
|
||||
const handler = NextAuth(authOptions);
|
||||
|
||||
export { handler as GET, handler as POST };
|
||||
21
apps/web/app/api/v1/memberships/route.ts
Normal file
21
apps/web/app/api/v1/memberships/route.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { getSessionUser } from "@/lib/api/apiHelper";
|
||||
import { prisma } from "@formbricks/database";
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
export async function GET() {
|
||||
const sessionUser = await getSessionUser();
|
||||
if (!sessionUser) {
|
||||
return new Response("Not authenticated", {
|
||||
status: 401,
|
||||
});
|
||||
}
|
||||
|
||||
// get memberships
|
||||
const memberships = await prisma.membership.findMany({
|
||||
where: {
|
||||
userId: sessionUser.id,
|
||||
},
|
||||
});
|
||||
|
||||
return NextResponse.json(memberships);
|
||||
}
|
||||
39
apps/web/app/api/v1/users/me/route.ts
Normal file
39
apps/web/app/api/v1/users/me/route.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { getSessionUser } from "@/lib/api/apiHelper";
|
||||
import { prisma } from "@formbricks/database";
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
|
||||
export async function GET() {
|
||||
const sessionUser = await getSessionUser();
|
||||
if (!sessionUser) {
|
||||
return new Response("Not authenticated", {
|
||||
status: 401,
|
||||
});
|
||||
}
|
||||
|
||||
const user = await prisma.user.findUnique({
|
||||
where: {
|
||||
email: sessionUser.email,
|
||||
},
|
||||
});
|
||||
|
||||
return NextResponse.json(user);
|
||||
}
|
||||
|
||||
export async function PUT(request: NextRequest) {
|
||||
const sessionUser = await getSessionUser();
|
||||
if (!sessionUser) {
|
||||
return new Response("Not authenticated", {
|
||||
status: 401,
|
||||
});
|
||||
}
|
||||
const body = await request.json();
|
||||
|
||||
const user = await prisma.user.update({
|
||||
where: {
|
||||
email: sessionUser.email,
|
||||
},
|
||||
data: body,
|
||||
});
|
||||
|
||||
return NextResponse.json(user);
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import EnvironmentsNavbar from "@/app/environments/[environmentId]/EnvironmentsN
|
||||
import ToasterClient from "@/components/ToasterClient";
|
||||
import { getServerSession } from "next-auth";
|
||||
import { redirect } from "next/navigation";
|
||||
import { authOptions } from "pages/api/auth/[...nextauth]";
|
||||
import { authOptions } from "@/app/api/auth/[...nextauth]/authOptions";
|
||||
import PosthogIdentify from "./PosthogIdentify";
|
||||
import FormbricksClient from "./FormbricksClient";
|
||||
import { PosthogClientWrapper } from "../../PosthogClientWrapper";
|
||||
|
||||
@@ -3,7 +3,7 @@ import SettingsTitle from "../SettingsTitle";
|
||||
import { Button } from "@formbricks/ui";
|
||||
import PricingTable from "./PricingTable";
|
||||
import { getServerSession } from "next-auth";
|
||||
import { authOptions } from "@/pages/api/auth/[...nextauth]";
|
||||
import { authOptions } from "@/app/api/auth/[...nextauth]/authOptions";
|
||||
|
||||
const proPlan = false;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import SettingsCard from "../SettingsCard";
|
||||
import SettingsTitle from "../SettingsTitle";
|
||||
import { getServerSession } from "next-auth";
|
||||
import { EditName, EditAvatar } from "./editProfile";
|
||||
import { authOptions } from "@/pages/api/auth/[...nextauth]";
|
||||
import { authOptions } from "@/app/api/auth/[...nextauth]/authOptions";
|
||||
|
||||
export default async function ProfileSettingsPage() {
|
||||
const session = await getServerSession(authOptions);
|
||||
|
||||
26
apps/web/app/error.tsx
Normal file
26
apps/web/app/error.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
"use client"; // Error components must be Client components
|
||||
|
||||
import { Button, ErrorComponent } from "@/../../packages/ui";
|
||||
import { useEffect } from "react";
|
||||
|
||||
export default function Error({ error, reset }: { error: Error; reset: () => void }) {
|
||||
useEffect(() => {
|
||||
// Log the error to an error reporting service
|
||||
console.error(error);
|
||||
}, [error]);
|
||||
|
||||
return (
|
||||
<div className="flex h-full w-full flex-col items-center justify-center">
|
||||
<ErrorComponent />
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={
|
||||
// Attempt to recover by trying to re-render the segment
|
||||
() => reset()
|
||||
}
|
||||
className="mt-2">
|
||||
Try again
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { sendInviteAcceptedEmail } from "@/lib/email";
|
||||
import { verifyInviteToken } from "@/lib/jwt";
|
||||
import { authOptions } from "@/pages/api/auth/[...nextauth]";
|
||||
import { authOptions } from "@/app/api/auth/[...nextauth]/authOptions";
|
||||
import { getServerSession } from "next-auth";
|
||||
import { env } from "process";
|
||||
import { prisma } from "@formbricks/database";
|
||||
|
||||
@@ -23,7 +23,7 @@ interface OnboardingProps {
|
||||
}
|
||||
|
||||
export default function Onboarding({ session }: OnboardingProps) {
|
||||
const { data, error } = useSWR(`/api/v1/environments/find-first`, fetcher);
|
||||
const { data: environment, error } = useSWR(`/api/v1/environments/find-first`, fetcher);
|
||||
const { profile } = useProfile();
|
||||
const { triggerProfileMutate } = useProfileMutation();
|
||||
const [currentStep, setCurrentStep] = useState(1);
|
||||
@@ -62,13 +62,13 @@ export default function Onboarding({ session }: OnboardingProps) {
|
||||
try {
|
||||
const updatedProfile = { ...profile, onboardingDisplayed: true };
|
||||
await triggerProfileMutate(updatedProfile);
|
||||
if (data) {
|
||||
await router.push(`/environments/${data.id}/surveys`);
|
||||
if (environment) {
|
||||
router.push(`/environments/${environment.id}/surveys`);
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
toast.error("An error occured saving your settings.");
|
||||
console.error(e);
|
||||
} finally {
|
||||
}
|
||||
};
|
||||
|
||||
@@ -92,7 +92,7 @@ export default function Onboarding({ session }: OnboardingProps) {
|
||||
{currentStep === 1 && <Greeting next={next} skip={skip} name={profile.name} session={session} />}
|
||||
{currentStep === 2 && <Role next={next} skip={skip} />}
|
||||
{currentStep === 3 && <Objective next={next} skip={skip} />}
|
||||
{currentStep === 4 && <Product done={done} environmentId={data.id} isLoading={isLoading} />}
|
||||
{currentStep === 4 && <Product done={done} environmentId={environment.id} isLoading={isLoading} />}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { getServerSession } from "next-auth";
|
||||
import Onboarding from "./Onboarding";
|
||||
import { authOptions } from "@/pages/api/auth/[...nextauth]";
|
||||
import { authOptions } from "@/app/api/auth/[...nextauth]/authOptions";
|
||||
|
||||
export default async function OnboardingPage() {
|
||||
const session = await getServerSession(authOptions);
|
||||
|
||||
@@ -1,21 +1,41 @@
|
||||
import LoadingSpinner from "@/components/shared/LoadingSpinner";
|
||||
import { WEBAPP_URL } from "@/../../packages/lib/constants";
|
||||
import { authOptions } from "@/app/api/auth/[...nextauth]/authOptions";
|
||||
import type { Session } from "next-auth";
|
||||
import { getServerSession } from "next-auth";
|
||||
import { headers } from "next/headers";
|
||||
import { redirect } from "next/navigation";
|
||||
import { authOptions } from "pages/api/auth/[...nextauth]";
|
||||
import { HomeRedirect } from "./HomeRedirect";
|
||||
import { PosthogClientWrapper } from "./PosthogClientWrapper";
|
||||
|
||||
async function getEnvironment() {
|
||||
const cookie = headers().get("cookie") || "";
|
||||
const res = await fetch(`${WEBAPP_URL}/api/v1/environments/find-first`, {
|
||||
headers: {
|
||||
cookie,
|
||||
},
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error("Failed to fetch data");
|
||||
}
|
||||
|
||||
return res.json();
|
||||
}
|
||||
|
||||
export default async function Home() {
|
||||
const session = await getServerSession(authOptions);
|
||||
const session: Session | null = await getServerSession(authOptions);
|
||||
|
||||
if (!session) {
|
||||
redirect("/auth/login");
|
||||
}
|
||||
return (
|
||||
<PosthogClientWrapper>
|
||||
<div>
|
||||
<HomeRedirect session={session} />
|
||||
<LoadingSpinner />
|
||||
</div>
|
||||
</PosthogClientWrapper>
|
||||
);
|
||||
|
||||
if (session?.user && !session?.user?.onboardingDisplayed) {
|
||||
return redirect(`/onboarding`);
|
||||
}
|
||||
|
||||
const environment = await getEnvironment();
|
||||
|
||||
if (!environment) {
|
||||
throw Error("No environment found for user");
|
||||
}
|
||||
|
||||
return redirect(`/environments/${environment.id}`);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { authOptions } from "@/pages/api/auth/[...nextauth]";
|
||||
import { authOptions } from "@/app/api/auth/[...nextauth]/authOptions";
|
||||
import { prisma } from "@formbricks/database";
|
||||
import { createHash } from "crypto";
|
||||
import { NextApiRequest, NextApiResponse } from "next";
|
||||
import type { Session } from "next-auth";
|
||||
import { getServerSession } from "next-auth";
|
||||
|
||||
export const hashApiKey = (key: string): string => createHash("sha256").update(key).digest("hex");
|
||||
@@ -115,8 +116,13 @@ export const hasTeamAccess = async (user, teamId) => {
|
||||
return false;
|
||||
};
|
||||
|
||||
export const getSessionUser = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
export const getSessionUser = async (req?: NextApiRequest, res?: NextApiResponse) => {
|
||||
// check for session (browser usage)
|
||||
let session: any = await getServerSession(req, res, authOptions);
|
||||
let session: Session | null;
|
||||
if (req && res) {
|
||||
session = await getServerSession(req, res, authOptions);
|
||||
} else {
|
||||
session = await getServerSession(authOptions);
|
||||
}
|
||||
if (session && "user" in session) return session.user;
|
||||
};
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { WEBAPP_URL } from "@formbricks/lib/constants";
|
||||
import { withEmailTemplate } from "./email-template";
|
||||
import { createInviteToken, createToken } from "./jwt";
|
||||
const nodemailer = require("nodemailer");
|
||||
@@ -32,10 +33,10 @@ export const sendVerificationEmail = async (user) => {
|
||||
const token = createToken(user.id, user.email, {
|
||||
expiresIn: "1d",
|
||||
});
|
||||
const verifyLink = `${process.env.NEXTAUTH_URL}/auth/verify?token=${encodeURIComponent(token)}`;
|
||||
const verificationRequestLink = `${
|
||||
process.env.NEXTAUTH_URL
|
||||
}/auth/verification-requested?email=${encodeURIComponent(user.email)}`;
|
||||
const verifyLink = `${WEBAPP_URL}/auth/verify?token=${encodeURIComponent(token)}`;
|
||||
const verificationRequestLink = `${WEBAPP_URL}/auth/verification-requested?email=${encodeURIComponent(
|
||||
user.email
|
||||
)}`;
|
||||
await sendEmail({
|
||||
to: user.email,
|
||||
subject: "Welcome to Formbricks 🤍",
|
||||
@@ -54,9 +55,7 @@ export const sendForgotPasswordEmail = async (user) => {
|
||||
const token = createToken(user.id, user.email, {
|
||||
expiresIn: "1d",
|
||||
});
|
||||
const verifyLink = `${process.env.NEXTAUTH_URL}/auth/forgot-password/reset?token=${encodeURIComponent(
|
||||
token
|
||||
)}`;
|
||||
const verifyLink = `${WEBAPP_URL}/auth/forgot-password/reset?token=${encodeURIComponent(token)}`;
|
||||
await sendEmail({
|
||||
to: user.email,
|
||||
subject: "Reset your Formbricks password",
|
||||
@@ -84,8 +83,7 @@ export const sendInviteMemberEmail = async (inviteId, inviterName, inviteeName,
|
||||
const token = createInviteToken(inviteId, email, {
|
||||
expiresIn: "7d",
|
||||
});
|
||||
// const verifyLink = `${process.env.NEXTAUTH_URL}/api/v1/invite?token=${encodeURIComponent(token)}`;
|
||||
const verifyLink = `${process.env.NEXTAUTH_URL}/invite?token=${encodeURIComponent(token)}`;
|
||||
const verifyLink = `${WEBAPP_URL}/invite?token=${encodeURIComponent(token)}`;
|
||||
|
||||
await sendEmail({
|
||||
to: email,
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
import { getSessionUser } from "@/lib/api/apiHelper";
|
||||
import { prisma } from "@formbricks/database";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
export default async function handle(req: NextApiRequest, res: NextApiResponse) {
|
||||
// Check Authentication
|
||||
const user: any = await getSessionUser(req, res);
|
||||
if (!user) {
|
||||
return res.status(401).json({ message: "Not authenticated" });
|
||||
}
|
||||
|
||||
// GET
|
||||
if (req.method === "GET") {
|
||||
// get memberships
|
||||
const memberships = await prisma.membership.findMany({
|
||||
where: {
|
||||
userId: user.id,
|
||||
},
|
||||
include: {
|
||||
team: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
products: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
environments: {
|
||||
select: {
|
||||
id: true,
|
||||
type: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
return res.json(memberships);
|
||||
}
|
||||
|
||||
// Unknown HTTP Method
|
||||
else {
|
||||
throw new Error(`The HTTP ${req.method} method is not supported by this route.`);
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
import { getSessionUser } from "@/lib/api/apiHelper";
|
||||
import { prisma } from "@formbricks/database";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
export default async function handle(req: NextApiRequest, res: NextApiResponse) {
|
||||
// Check Authentication
|
||||
const session = await getSessionUser(req, res);
|
||||
if (!session) {
|
||||
return res.status(401).json({ message: "Not authenticated" });
|
||||
}
|
||||
|
||||
// GET /api/users/me
|
||||
// Get the current user
|
||||
if (req.method === "GET") {
|
||||
const user = await prisma.user.findUnique({
|
||||
where: {
|
||||
email: session.email,
|
||||
},
|
||||
/* select: {
|
||||
id: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
email: true,
|
||||
name: true,
|
||||
identityProvider: true,
|
||||
}, */
|
||||
});
|
||||
return res.json(user);
|
||||
} // GET /api/users/me
|
||||
// Get the current user
|
||||
else if (req.method === "PUT") {
|
||||
const user = await prisma.user.update({
|
||||
where: {
|
||||
email: session.email,
|
||||
},
|
||||
data: req.body,
|
||||
});
|
||||
return res.json(user);
|
||||
}
|
||||
|
||||
// Unknown HTTP Method
|
||||
else {
|
||||
throw new Error(`The HTTP ${req.method} method is not supported by this route.`);
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,15 @@
|
||||
export const RESPONSES_LIMIT_FREE = 100;
|
||||
export const IS_FORMBRICKS_CLOUD = process.env.NEXT_PUBLIC_IS_FORMBRICKS_CLOUD !== "1";
|
||||
|
||||
// URLs
|
||||
const VERCEL_URL = process.env.NEXT_PUBLIC_VERCEL_URL ? `https://${process.env.NEXT_PUBLIC_VERCEL_URL}` : "";
|
||||
const RAILWAY_STATIC_URL = process.env.RAILWAY_STATIC_URL ? `https://${process.env.RAILWAY_STATIC_URL}` : "";
|
||||
const HEROKU_URL = process.env.HEROKU_APP_NAME ? `https://${process.env.HEROKU_APP_NAME}.herokuapp.com` : "";
|
||||
const RENDER_URL = process.env.RENDER_EXTERNAL_URL ? `https://${process.env.RENDER_EXTERNAL_URL}` : "";
|
||||
export const WEBAPP_URL =
|
||||
process.env.NEXT_PUBLIC_WEBAPP_URL ||
|
||||
VERCEL_URL ||
|
||||
RAILWAY_STATIC_URL ||
|
||||
HEROKU_URL ||
|
||||
RENDER_URL ||
|
||||
"http://localhost:3000";
|
||||
|
||||
@@ -7,7 +7,6 @@ export const captureTelemetry = async (eventName: string, properties = {}) => {
|
||||
if (
|
||||
process.env.TELEMETRY_DISABLED !== "1" &&
|
||||
process.env.NODE_ENV === "production" &&
|
||||
process.env.NEXTAUTH_URL !== "http://localhost:3000" &&
|
||||
process.env.INSTANCE_ID
|
||||
) {
|
||||
try {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"FORMBRICKS_LEGACY_HOST",
|
||||
"GITHUB_ID",
|
||||
"GITHUB_SECRET",
|
||||
"HEROKU_APP_NAME",
|
||||
"INSTANCE_ID",
|
||||
"MAIL_FROM",
|
||||
"NEXT_PUBLIC_EMAIL_VERIFICATION_DISABLED",
|
||||
@@ -38,12 +39,16 @@
|
||||
"NEXT_PUBLIC_FORMBRICKS_PMF_FORM_ID",
|
||||
"NEXT_PUBLIC_FORMBRICKS_URL",
|
||||
"NEXT_PUBLIC_IMPRINT_URL",
|
||||
"NEXT_PUBLIC_VERCEL_URL",
|
||||
"NODE_ENV",
|
||||
"NEXT_PUBLIC_POSTHOG_API_HOST",
|
||||
"NEXT_PUBLIC_POSTHOG_API_KEY",
|
||||
"NEXT_PUBLIC_FORMBRICKS_COM_API_HOST",
|
||||
"NEXT_PUBLIC_FORMBRICKS_COM_ENVIRONMENT_ID",
|
||||
"NEXT_PUBLIC_FORMBRICKS_COM_DOCS_FEEDBACK_SURVEY_ID",
|
||||
"NEXT_PUBLIC_WEBAPP_URL",
|
||||
"RAILWAY_STATIC_URL",
|
||||
"RENDER_EXTERNAL_URL",
|
||||
"SENTRY_DSN",
|
||||
"TELEMETRY_DISABLED",
|
||||
"VERCEL_URL"
|
||||
|
||||
Reference in New Issue
Block a user