Skip to content

Commit

Permalink
Merge branch 'fix-next-public' into docker-emulator
Browse files Browse the repository at this point in the history
  • Loading branch information
fomalhautb committed Feb 8, 2025
2 parents 2386a2a + a98bcb8 commit 34cfb41
Show file tree
Hide file tree
Showing 16 changed files with 96 additions and 23 deletions.
6 changes: 4 additions & 2 deletions apps/dashboard/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ module.exports = {
message:
"Importing useRouter from next/navigation or next/router is not allowed. Use our custom useRouter instead.",
},
],
patterns: [
{
group: ["next/link"],
message:
Expand All @@ -26,6 +24,10 @@ module.exports = {
],
"no-restricted-syntax": [
...defaults.rules["no-restricted-syntax"].filter(e => typeof e !== "object" || !e.message.includes("yupXyz")),
{
selector: "MemberExpression[object.name='process'][property.name='env'][parent.property.name=/^NEXT_PUBLIC_/]",
message: "Direct access to process.env.NEXT_PUBLIC_* is not allowed. Use getPublicEnvVar() instead."
}
],
},
};
3 changes: 2 additions & 1 deletion apps/dashboard/sentry.client.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The config you add here will be used whenever a users loads a page in their browser.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/

import { getPublicEnvVar } from "@/lib/env";
import * as Sentry from "@sentry/nextjs";
import { getBrowserCompatibilityReport } from "@stackframe/stack-shared/dist/utils/browser-compat";
import { sentryBaseConfig } from "@stackframe/stack-shared/dist/utils/sentry";
Expand All @@ -10,7 +11,7 @@ import { nicify } from "@stackframe/stack-shared/dist/utils/strings";
Sentry.init({
...sentryBaseConfig,

dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
dsn: getPublicEnvVar('NEXT_PUBLIC_SENTRY_DSN'),

enabled: process.env.NODE_ENV !== "development" && !process.env.CI,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { FormDialog } from "@/components/form-dialog";
import { InputField, SwitchField } from "@/components/form-fields";
import { SettingIconButton, SettingSwitch } from "@/components/settings";
import { getPublicEnvVar } from "@/lib/env";
import { AdminProject } from "@stackframe/stack";
import { yupBoolean, yupObject, yupString } from "@stackframe/stack-shared/dist/schema-fields";
import { sharedProviders } from "@stackframe/stack-shared/dist/utils/oauth";
Expand Down Expand Up @@ -109,7 +110,7 @@ export function ProviderSettingDialog(props: Props & { open: boolean, onClose: (
Redirect URL for the OAuth provider settings
</Label>
<Typography type="footnote">
<InlineCode>{`${process.env.NEXT_PUBLIC_STACK_API_URL}/api/v1/auth/oauth/callback/${props.id}`}</InlineCode>
<InlineCode>{`${getPublicEnvVar('NEXT_PUBLIC_STACK_API_URL')}/api/v1/auth/oauth/callback/${props.id}`}</InlineCode>
</Typography>
</div>}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export function OnboardingDialog() {
>
<div className="flex flex-col gap-2">
<Typography className="mb-4">
Congratulations on creating your new project! We have automatically created an API key for you. Please copy it to your <InlineCode>.env.local</InlineCode> file. Get more information in the <StyledLink target="_blank" href="https://docs.stack-auth.com">getting started guide</StyledLink>.
Congratulations on creating your new project! We have automatically created an API key for you. Please copy it to your <InlineCode>.env.local</InlineCode> file. Get more information in the <StyledLink target="_blank" href="https://docs.stack-auth.com">Getting Started guide</StyledLink>.
</Typography>
<EnvKeys projectId={project.id} publishableClientKey={apiKey?.publishableClientKey} secretServerKey={apiKey?.secretServerKey} />
<Typography type="label">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { InputField, SwitchField } from "@/components/form-fields";
import { StyledLink } from "@/components/link";
import { FormSettingCard, SettingCard, SettingSwitch, SettingText } from "@/components/settings";
import { getPublicEnvVar } from "@/lib/env";
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, ActionDialog, Alert, Button, Typography } from "@stackframe/stack-ui";
import * as yup from "yup";
import { PageLayout } from "../page-layout";
Expand Down Expand Up @@ -31,7 +32,7 @@ export default function PageClient() {
</SettingText>

<SettingText label="JWKS URL">
{`${process.env.NEXT_PUBLIC_STACK_API_URL}/api/v1/projects/${project.id}/.well-known/jwks.json`}
{`${getPublicEnvVar('NEXT_PUBLIC_STACK_API_URL')}/api/v1/projects/${project.id}/.well-known/jwks.json`}
</SettingText>
</SettingCard>
<FormSettingCard
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
"use client";

import { SettingCard, SettingSwitch } from "@/components/settings";
import { getPublicEnvVar } from "@/lib/env";
import { runAsynchronously } from "@stackframe/stack-shared/dist/utils/promises";
import { Alert, Badge, Button, Checkbox, CopyButton, Label, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Typography } from "@stackframe/stack-ui";
import { ChevronLeft, ChevronRight } from "lucide-react";
import { useEffect, useMemo, useState } from "react";
import { SvixProvider, useEndpoint, useEndpointFunctions, useEndpointMessageAttempts, useEndpointSecret, useSvix } from "svix-react";
import { useMemo, useState } from "react";
import { SvixProvider, useEndpoint, useEndpointFunctions, useEndpointMessageAttempts, useEndpointSecret } from "svix-react";
import { PageLayout } from "../../page-layout";
import { useAdminApp } from "../../use-admin-app";
import { getSvixResult } from "../utils";
Expand Down Expand Up @@ -187,7 +188,7 @@ export default function PageClient(props: { endpointId: string }) {
<SvixProvider
token={svixTokenUpdated}
appId={stackAdminApp.projectId}
options={{ serverUrl: process.env.NEXT_PUBLIC_STACK_SVIX_SERVER_URL }}
options={{ serverUrl: getPublicEnvVar('NEXT_PUBLIC_STACK_SVIX_SERVER_URL') }}
>
<PageInner endpointId={props.endpointId} />
</SvixProvider>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
"use client";

import { SmartFormDialog } from "@/components/form-dialog";
import { useRouter } from "@/components/router";
import { SettingCard } from "@/components/settings";
import { getPublicEnvVar } from "@/lib/env";
import { urlSchema } from "@stackframe/stack-shared/dist/schema-fields";
import { ActionCell, ActionDialog, Alert, Button, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Typography } from "@stackframe/stack-ui";
import { useRouter } from "next/navigation";
import { useMemo, useState } from "react";
import { SvixProvider, useEndpoints, useSvix } from "svix-react";
import * as yup from "yup";
Expand Down Expand Up @@ -192,7 +193,7 @@ export default function PageClient() {
<SvixProvider
token={svixTokenUpdated}
appId={stackAdminApp.projectId}
options={{ serverUrl: process.env.NEXT_PUBLIC_STACK_SVIX_SERVER_URL }}
options={{ serverUrl: getPublicEnvVar('NEXT_PUBLIC_STACK_SVIX_SERVER_URL') }}
>
<Endpoints updateFn={() => setUpdateCounter(x => x + 1)} />
</SvixProvider>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
"use client";

import { Logo } from "@/components/logo";
import { useRouter } from "@/components/router";
import { useStackApp, useUser } from "@stackframe/stack";
import { wait } from "@stackframe/stack-shared/dist/utils/promises";
import { Button, Card, CardContent, CardFooter, CardHeader, Input, Typography } from "@stackframe/stack-ui";
import Image from "next/image";
import { useRouter, useSearchParams } from "next/navigation";
import { useSearchParams } from "next/navigation";
import NeonLogo from "../../../../../../../../public/neon.png";

export const stackAppInternalsSymbol = Symbol.for("StackAuth--DO-NOT-USE-OR-YOU-WILL-BE-FIRED--StackAppInternals");
Expand Down
8 changes: 5 additions & 3 deletions apps/dashboard/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { RouterProvider } from '@/components/router';
import { SiteLoadingIndicatorDisplay } from '@/components/site-loading-indicator';
import { StyleLink } from '@/components/style-link';
import { ThemeProvider } from '@/components/theme-provider';
import { getPublicEnvVar } from '@/lib/env';
import { cn } from '@/lib/utils';
import { stackServerApp } from '@/stack';
import { StackProvider, StackTheme } from '@stackframe/stack';
Expand All @@ -23,7 +24,7 @@ import './globals.css';
import { CSPostHogProvider, UserIdentity } from './providers';

export const metadata: Metadata = {
metadataBase: new URL(process.env.NEXT_PUBLIC_STACK_API_URL || ''),
metadataBase: new URL(getPublicEnvVar('NEXT_PUBLIC_STACK_API_URL') || ''),
title: {
default: 'Stack Auth Dashboard',
template: '%s | Stack Auth',
Expand All @@ -32,12 +33,12 @@ export const metadata: Metadata = {
openGraph: {
title: 'Stack Auth Dashboard',
description: 'Stack Auth is the open-source Auth0 alternative, and the fastest way to add authentication to your web app.',
images: [`${process.env.NEXT_PUBLIC_STACK_API_URL}/open-graph-image.png`]
images: [`${getPublicEnvVar('NEXT_PUBLIC_STACK_API_URL')}/open-graph-image.png`]
},
twitter: {
title: 'Stack Auth Dashboard',
description: 'Stack Auth is the open-source Auth0 alternative, and the fastest way to add authentication to your web app.',
images: [`${process.env.NEXT_PUBLIC_STACK_API_URL}/open-graph-image.png`]
images: [`${getPublicEnvVar('NEXT_PUBLIC_STACK_API_URL')}/open-graph-image.png`]
},
};

Expand Down Expand Up @@ -70,6 +71,7 @@ export default function RootLayout({
return (
<html suppressHydrationWarning lang="en" className={`${GeistSans.variable} ${GeistMono.variable}`}>
<head>
{getNodeEnvironment() === 'development' && <script src="https://unpkg.com/react-scan/dist/auto.global.js" async />}
<link rel="preconnect" href="https://fonts.gstatic.com" />
<StyleLink href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded&display=block" />
<StyleLink defer href="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.css" integrity="sha384-OH8qNTHoMMVNVcKdKewlipV4SErXqccxxlg6HC9Cwjr5oZu2AdBej1TndeCirael" crossOrigin="anonymous" />
Expand Down
3 changes: 2 additions & 1 deletion apps/dashboard/src/app/providers.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
'use client';
import { getPublicEnvVar } from '@/lib/env';
import { useStackApp, useUser } from '@stackframe/stack';
import posthog from 'posthog-js';
import { PostHogProvider } from 'posthog-js/react';
import { Suspense, useEffect, useState } from 'react';

if (typeof window !== 'undefined') {
const postHogKey = process.env.NEXT_PUBLIC_POSTHOG_KEY ?? "phc_vIUFi0HzHo7oV26OsaZbUASqxvs8qOmap1UBYAutU4k";
const postHogKey = getPublicEnvVar('NEXT_PUBLIC_POSTHOG_KEY') ?? "phc_vIUFi0HzHo7oV26OsaZbUASqxvs8qOmap1UBYAutU4k";
if (postHogKey.length > 5) {
posthog.init(postHogKey, {
api_host: "/consume",
Expand Down
3 changes: 2 additions & 1 deletion apps/dashboard/src/components/env-keys.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { getPublicEnvVar } from "@/lib/env";
import { Button, CopyField, Tabs, TabsContent, TabsList, TabsTrigger } from "@stackframe/stack-ui";

export default function EnvKeys(props: {
Expand All @@ -7,7 +8,7 @@ export default function EnvKeys(props: {
superSecretAdminKey?: string,
}) {
const envFileContent = Object.entries({
NEXT_PUBLIC_STACK_API_URL: process.env.NEXT_PUBLIC_STACK_API_URL === "https://api.stack-auth.com" ? undefined : process.env.NEXT_PUBLIC_STACK_API_URL,
NEXT_PUBLIC_STACK_API_URL: getPublicEnvVar('NEXT_PUBLIC_STACK_API_URL') === "https://api.stack-auth.com" ? undefined : getPublicEnvVar('NEXT_PUBLIC_STACK_API_URL'),
NEXT_PUBLIC_STACK_PROJECT_ID: props.projectId,
NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY: props.publishableClientKey,
STACK_SECRET_SERVER_KEY: props.secretServerKey,
Expand Down
3 changes: 2 additions & 1 deletion apps/dashboard/src/components/version-alerter.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use client";

import { getPublicEnvVar } from "@/lib/env";
import { runAsynchronously, wait } from "@stackframe/stack-shared/dist/utils/promises";
import { useEffect, useState } from "react";
import packageJson from "../../package.json";
Expand All @@ -14,7 +15,7 @@ export function VersionAlerter({ severeOnly }: { severeOnly: boolean }) {
// IMPORTANT: THIS ENVIRONMENT VARIABLE IS UNDOCUMENTED AND NOT MEANT FOR PRODUCTION USAGE
// AND YOU SHOULD ALWAYS KEEP STACK AUTH UP TO DATE. WE CAN'T APPLY SECURITY UPDATES IF
// YOU DON'T UPDATE STACK AUTH REGULARLY.
const enableNonSevereVersionCheck = process.env.NEXT_PUBLIC_VERSION_ALERTER_SEVERE_ONLY !== "true";
const enableNonSevereVersionCheck = getPublicEnvVar('NEXT_PUBLIC_VERSION_ALERTER_SEVERE_ONLY') !== "true";

useEffect(() => {
if (window.location.origin === "https://app.stack-auth.com") {
Expand Down
39 changes: 39 additions & 0 deletions apps/dashboard/src/lib/env.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/* eslint-disable no-restricted-syntax */

const _inlineEnvVars = {
NEXT_PUBLIC_STACK_API_URL: process.env.NEXT_PUBLIC_STACK_API_URL,
NEXT_PUBLIC_STACK_DASHBOARD_URL: process.env.NEXT_PUBLIC_STACK_DASHBOARD_URL,
NEXT_PUBLIC_STACK_PROJECT_ID: process.env.NEXT_PUBLIC_STACK_PROJECT_ID,
NEXT_PUBLIC_POSTHOG_KEY: process.env.NEXT_PUBLIC_POSTHOG_KEY,
NEXT_PUBLIC_STACK_SVIX_SERVER_URL: process.env.NEXT_PUBLIC_STACK_SVIX_SERVER_URL,
NEXT_PUBLIC_SENTRY_DSN: process.env.NEXT_PUBLIC_SENTRY_DSN,
NEXT_PUBLIC_VERSION_ALERTER_SEVERE_ONLY: process.env.NEXT_PUBLIC_VERSION_ALERTER_SEVERE_ONLY,
};

// This will be replaced with the actual env vars after a docker build
const _postBuildEnvVars = {
NEXT_PUBLIC_STACK_API_URL: "STACK_ENV_VAR_SENTINEL_NEXT_PUBLIC_STACK_API_URL",
NEXT_PUBLIC_STACK_DASHBOARD_URL: "STACK_ENV_VAR_SENTINEL_NEXT_PUBLIC_STACK_DASHBOARD_URL",
NEXT_PUBLIC_STACK_PROJECT_ID: "STACK_ENV_VAR_SENTINEL_NEXT_PUBLIC_STACK_PROJECT_ID",
NEXT_PUBLIC_POSTHOG_KEY: "STACK_ENV_VAR_SENTINEL_NEXT_PUBLIC_POSTHOG_KEY",
NEXT_PUBLIC_STACK_SVIX_SERVER_URL: "STACK_ENV_VAR_SENTINEL_NEXT_PUBLIC_STACK_SVIX_SERVER_URL",
NEXT_PUBLIC_SENTRY_DSN: "STACK_ENV_VAR_SENTINEL_NEXT_PUBLIC_SENTRY_DSN",
NEXT_PUBLIC_VERSION_ALERTER_SEVERE_ONLY: "STACK_ENV_VAR_SENTINEL_NEXT_PUBLIC_VERSION_ALERTER_SEVERE_ONLY",
} satisfies Record<keyof typeof _inlineEnvVars, string>;

// If this is not replaced with "true", then we will not use inline env vars
const _usePostBuildEnvVars = 'STACK_ENV_VAR_SENTINEL_USE_INLINE_ENV_VARS';

export function getPublicEnvVar(name: keyof typeof _inlineEnvVars) {
eval("// this is a hack to force the compiler not to do any smart optimizations");
if (_usePostBuildEnvVars.slice(0) === 'true') {
const value = _postBuildEnvVars[name];
if (value.startsWith('STACK_ENV_VAR_SENTINEL')) {
return undefined;
}
return value;
} else {
return _inlineEnvVars[name];
}
}

6 changes: 3 additions & 3 deletions apps/dashboard/src/stack.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import './polyfills';

import { StackServerApp } from '@stackframe/stack';
import { getPublicEnvVar } from './lib/env';
import './polyfills';

if (process.env.NEXT_PUBLIC_STACK_PROJECT_ID !== "internal") {
if (getPublicEnvVar("NEXT_PUBLIC_STACK_PROJECT_ID") !== "internal") {
throw new Error("This project is not configured correctly. stack-dashboard must always use the internal project.");
}

Expand Down
21 changes: 21 additions & 0 deletions docker/server/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,27 @@ else
cd ../..
fi

# Replace env var sentinel in dashboard build output
echo "Replacing env var sentinel in dashboard build output..."
declare -A replacements=(
["STACK_ENV_VAR_SENTINEL_USE_INLINE_ENV_VARS"]="true"
["STACK_ENV_VAR_SENTINEL_NEXT_PUBLIC_STACK_PROJECT_ID"]="${NEXT_PUBLIC_STACK_PROJECT_ID}"
["STACK_ENV_VAR_SENTINEL_NEXT_PUBLIC_STACK_API_URL"]="${NEXT_PUBLIC_STACK_API_URL}"
["STACK_ENV_VAR_SENTINEL_NEXT_PUBLIC_STACK_DASHBOARD_URL"]="${NEXT_PUBLIC_STACK_DASHBOARD_URL}"
["STACK_ENV_VAR_SENTINEL_NEXT_PUBLIC_POSTHOG_KEY"]="${NEXT_PUBLIC_POSTHOG_KEY}"
["STACK_ENV_VAR_SENTINEL_NEXT_PUBLIC_STACK_SVIX_SERVER_URL"]="${NEXT_PUBLIC_STACK_SVIX_SERVER_URL}"
["STACK_ENV_VAR_SENTINEL_NEXT_PUBLIC_SENTRY_DSN"]="${NEXT_PUBLIC_SENTRY_DSN}"
["STACK_ENV_VAR_SENTINEL_NEXT_PUBLIC_VERSION_ALERTER_SEVERE_ONLY"]="${NEXT_PUBLIC_VERSION_ALERTER_SEVERE_ONLY}"
)

for key in "${!replacements[@]}"; do
value="${replacements[$key]}"
# Escape special characters in both key and value
escaped_key=$(printf '%s\n' "$key" | sed 's/[[\.*^$/]/\\&/g')
escaped_value=$(printf '%s\n' "$value" | sed 's/[[\.*^$/]/\\&/g')
find /app/apps -type f -exec sed -i "s/$escaped_key/$escaped_value/g" {} +
done

# Start backend and dashboard in parallel
echo "Starting backend on port $BACKEND_PORT..."
PORT=$BACKEND_PORT HOSTNAME=0.0.0.0 node apps/backend/server.js &
Expand Down
4 changes: 2 additions & 2 deletions docs/fern/docs/pages/customization/custom-styles.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ And some other variables:

These variables are css variables so you can use the syntax like `hsl(0, 0%, 0%)`, `black`, `#fff`, etc.

The colors can be different for light and dark mode. You can pass these into the `StackTheme` component (in your `layout.tsx` file if you followed the get started guide) as follows:
The colors can be different for light and dark mode. You can pass these into the `StackTheme` component (in your `layout.tsx` file if you followed the Getting Started guide) as follows:

```jsx title="app/layout.tsx"
const theme = {
Expand All @@ -50,4 +50,4 @@ const theme = {
<StackTheme theme={theme}>
{/* children */}
</StackTheme>
```
```

0 comments on commit 34cfb41

Please sign in to comment.