feat: runtime env

Support runtime environment variables using server components.

This will mean docker images can change env vars for runtime as required.
This commit is contained in:
Mythie
2023-11-12 13:10:30 +11:00
parent aec0d2ae97
commit 1cd60e1abb
29 changed files with 254 additions and 70 deletions

View File

@ -8,10 +8,13 @@ import { getPortalSession } from '@documenso/ee/server-only/stripe/get-portal-se
import { getRequiredServerComponentSession } from '@documenso/lib/next-auth/get-server-session';
import { Stripe, stripe } from '@documenso/lib/server-only/stripe';
import { getSubscriptionByUserId } from '@documenso/lib/server-only/subscription/get-subscription-by-user-id';
import { getRuntimeEnv } from '@documenso/lib/universal/runtime-env/get-runtime-env';
export const createBillingPortal = async () => {
const { user } = await getRequiredServerComponentSession();
const { NEXT_PUBLIC_WEBAPP_URL } = getRuntimeEnv();
const existingSubscription = await getSubscriptionByUserId({ userId: user.id });
let stripeCustomer: Stripe.Customer | null = null;
@ -43,6 +46,6 @@ export const createBillingPortal = async () => {
return getPortalSession({
customerId: stripeCustomer.id,
returnUrl: `${process.env.NEXT_PUBLIC_WEBAPP_URL}/settings/billing`,
returnUrl: `${NEXT_PUBLIC_WEBAPP_URL}/settings/billing`,
});
};

View File

@ -10,6 +10,7 @@ import { getPortalSession } from '@documenso/ee/server-only/stripe/get-portal-se
import { getRequiredServerComponentSession } from '@documenso/lib/next-auth/get-server-session';
import { Stripe } from '@documenso/lib/server-only/stripe';
import { getSubscriptionByUserId } from '@documenso/lib/server-only/subscription/get-subscription-by-user-id';
import { getRuntimeEnv } from '@documenso/lib/universal/runtime-env/get-runtime-env';
export type CreateCheckoutOptions = {
priceId: string;
@ -18,6 +19,8 @@ export type CreateCheckoutOptions = {
export const createCheckout = async ({ priceId }: CreateCheckoutOptions) => {
const { user } = await getRequiredServerComponentSession();
const { NEXT_PUBLIC_WEBAPP_URL } = getRuntimeEnv();
const existingSubscription = await getSubscriptionByUserId({ userId: user.id });
let stripeCustomer: Stripe.Customer | null = null;
@ -32,7 +35,7 @@ export const createCheckout = async ({ priceId }: CreateCheckoutOptions) => {
return getPortalSession({
customerId: stripeCustomer.id,
returnUrl: `${process.env.NEXT_PUBLIC_WEBAPP_URL}/settings/billing`,
returnUrl: `${NEXT_PUBLIC_WEBAPP_URL}/settings/billing`,
});
}
@ -53,6 +56,6 @@ export const createCheckout = async ({ priceId }: CreateCheckoutOptions) => {
return getCheckoutSession({
customerId: stripeCustomer.id,
priceId,
returnUrl: `${process.env.NEXT_PUBLIC_WEBAPP_URL}/settings/billing`,
returnUrl: `${NEXT_PUBLIC_WEBAPP_URL}/settings/billing`,
});
};

View File

@ -2,7 +2,8 @@ import { Metadata } from 'next';
import { headers } from 'next/headers';
import { redirect } from 'next/navigation';
import { APP_BASE_URL } from '@documenso/lib/constants/app';
import { appBaseUrl } from '@documenso/lib/constants/app';
import { getRuntimeEnv } from '@documenso/lib/universal/runtime-env/get-runtime-env';
type SharePageProps = {
params: { slug: string };
@ -16,12 +17,12 @@ export function generateMetadata({ params: { slug } }: SharePageProps) {
title: 'Documenso - Join the open source signing revolution',
description: 'I just signed with Documenso!',
type: 'website',
images: [`${APP_BASE_URL}/share/${slug}/opengraph`],
images: [`${appBaseUrl()}/share/${slug}/opengraph`],
},
twitter: {
site: '@documenso',
card: 'summary_large_image',
images: [`${APP_BASE_URL}/share/${slug}/opengraph`],
images: [`${appBaseUrl()}/share/${slug}/opengraph`],
description: 'I just signed with Documenso!',
},
} satisfies Metadata;
@ -30,10 +31,12 @@ export function generateMetadata({ params: { slug } }: SharePageProps) {
export default function SharePage() {
const userAgent = headers().get('User-Agent') ?? '';
const { NEXT_PUBLIC_MARKETING_URL } = getRuntimeEnv();
// https://stackoverflow.com/questions/47026171/how-to-detect-bots-for-open-graph-with-user-agent
if (/bot|facebookexternalhit|WhatsApp|google|bing|duckduckbot|MetaInspector/i.test(userAgent)) {
return null;
}
redirect(process.env.NEXT_PUBLIC_MARKETING_URL ?? 'http://localhost:3001');
redirect(NEXT_PUBLIC_MARKETING_URL ?? 'http://localhost:3001');
}

View File

@ -6,6 +6,8 @@ import { FeatureFlagProvider } from '@documenso/lib/client-only/providers/featur
import { LocaleProvider } from '@documenso/lib/client-only/providers/locale';
import { getServerComponentAllFlags } from '@documenso/lib/server-only/feature-flags/get-server-component-feature-flag';
import { getLocale } from '@documenso/lib/server-only/headers/get-locale';
import { RuntimeEnvProvider } from '@documenso/lib/universal/runtime-env';
import { getRuntimeEnv } from '@documenso/lib/universal/runtime-env/get-runtime-env';
import { TrpcProvider } from '@documenso/trpc/react';
import { cn } from '@documenso/ui/lib/utils';
import { Toaster } from '@documenso/ui/primitives/toaster';
@ -17,31 +19,39 @@ import { PostHogPageview } from '~/providers/posthog';
import './globals.css';
export const dynamic = 'force-dynamic';
const fontInter = Inter({ subsets: ['latin'], variable: '--font-sans' });
const fontCaveat = Caveat({ subsets: ['latin'], variable: '--font-signature' });
export const metadata = {
title: 'Documenso - The Open Source DocuSign Alternative',
description:
'Join Documenso, the open signing infrastructure, and get a 10x better signing experience. Pricing starts at $30/mo. forever! Sign in now and enjoy a faster, smarter, and more beautiful document signing process. Integrates with your favorite tools, customizable, and expandable. Support our mission and become a part of our open-source community.',
keywords:
'Documenso, open source, DocuSign alternative, document signing, open signing infrastructure, open-source community, fast signing, beautiful signing, smart templates',
authors: { name: 'Documenso, Inc.' },
robots: 'index, follow',
openGraph: {
// We do this so NEXT_PUBLIC variables will be evaluated at runtime.
// eslint-disable-next-line @typescript-eslint/require-await
export const generateMetadata = async () => {
const { NEXT_PUBLIC_WEBAPP_URL } = getRuntimeEnv();
return {
title: 'Documenso - The Open Source DocuSign Alternative',
description:
'Join Documenso, the open signing infrastructure, and get a 10x better signing experience. Pricing starts at $30/mo. forever! Sign in now and enjoy a faster, smarter, and more beautiful document signing process. Integrates with your favorite tools, customizable, and expandable. Support our mission and become a part of our open-source community.',
type: 'website',
images: [`${process.env.NEXT_PUBLIC_WEBAPP_URL}/opengraph-image.jpg`],
},
twitter: {
site: '@documenso',
card: 'summary_large_image',
images: [`${process.env.NEXT_PUBLIC_WEBAPP_URL}/opengraph-image.jpg`],
description:
'Join Documenso, the open signing infrastructure, and get a 10x better signing experience. Pricing starts at $30/mo. forever! Sign in now and enjoy a faster, smarter, and more beautiful document signing process. Integrates with your favorite tools, customizable, and expandable. Support our mission and become a part of our open-source community.',
},
keywords:
'Documenso, open source, DocuSign alternative, document signing, open signing infrastructure, open-source community, fast signing, beautiful signing, smart templates',
authors: { name: 'Documenso, Inc.' },
robots: 'index, follow',
openGraph: {
title: 'Documenso - The Open Source DocuSign Alternative',
description:
'Join Documenso, the open signing infrastructure, and get a 10x better signing experience. Pricing starts at $30/mo. forever! Sign in now and enjoy a faster, smarter, and more beautiful document signing process. Integrates with your favorite tools, customizable, and expandable. Support our mission and become a part of our open-source community.',
type: 'website',
images: [`${NEXT_PUBLIC_WEBAPP_URL}/opengraph-image.jpg`],
},
twitter: {
site: '@documenso',
card: 'summary_large_image',
images: [`${NEXT_PUBLIC_WEBAPP_URL}/opengraph-image.jpg`],
description:
'Join Documenso, the open signing infrastructure, and get a 10x better signing experience. Pricing starts at $30/mo. forever! Sign in now and enjoy a faster, smarter, and more beautiful document signing process. Integrates with your favorite tools, customizable, and expandable. Support our mission and become a part of our open-source community.',
},
};
};
export default async function RootLayout({ children }: { children: React.ReactNode }) {
@ -67,19 +77,21 @@ export default async function RootLayout({ children }: { children: React.ReactNo
</Suspense>
<body>
<LocaleProvider locale={locale}>
<FeatureFlagProvider initialFlags={flags}>
<PlausibleProvider>
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
<TooltipProvider>
<TrpcProvider>{children}</TrpcProvider>
</TooltipProvider>
</ThemeProvider>
</PlausibleProvider>
<RuntimeEnvProvider>
<LocaleProvider locale={locale}>
<FeatureFlagProvider initialFlags={flags}>
<PlausibleProvider>
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
<TooltipProvider>
<TrpcProvider>{children}</TrpcProvider>
</TooltipProvider>
</ThemeProvider>
</PlausibleProvider>
<Toaster />
</FeatureFlagProvider>
</LocaleProvider>
<Toaster />
</FeatureFlagProvider>
</LocaleProvider>
</RuntimeEnvProvider>
</body>
</html>
);

View File

@ -1,3 +1,5 @@
import { getRuntimeEnv } from '@documenso/lib/universal/runtime-env/get-runtime-env';
/**
* getAssetBuffer is used to retrieve array buffers for various assets
* that are hosted in the `public` folder.
@ -8,7 +10,9 @@
* @param path The path to the asset, relative to the `public` folder.
*/
export const getAssetBuffer = async (path: string) => {
const baseUrl = process.env.NEXT_PUBLIC_WEBAPP_URL || 'http://localhost:3000';
const { NEXT_PUBLIC_WEBAPP_URL } = getRuntimeEnv();
const baseUrl = NEXT_PUBLIC_WEBAPP_URL || 'http://localhost:3000';
return fetch(new URL(path, baseUrl)).then(async (res) => res.arrayBuffer());
};