refactor(app): scope heavy providers to authenticated route layouts
This commit is contained in:
31
app/(app)/layout.tsx
Normal file
31
app/(app)/layout.tsx
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import * as Sentry from "@sentry/nextjs";
|
||||||
|
|
||||||
|
import { InitUser } from "@/components/init-user";
|
||||||
|
import { AppProviders } from "@/components/providers";
|
||||||
|
import { getAuthUser, getToken } from "@/lib/auth-server";
|
||||||
|
|
||||||
|
export default async function AuthenticatedAppLayout({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}) {
|
||||||
|
const initialToken = await getToken();
|
||||||
|
const user = await getAuthUser();
|
||||||
|
|
||||||
|
if (user) {
|
||||||
|
const id = user.userId ?? String(user._id);
|
||||||
|
Sentry.setUser({
|
||||||
|
id,
|
||||||
|
email: user.email ?? undefined,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Sentry.setUser(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AppProviders initialToken={initialToken}>
|
||||||
|
<InitUser />
|
||||||
|
{children}
|
||||||
|
</AppProviders>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
import { AuthView } from "@daveyplate/better-auth-ui";
|
import { AuthView } from "@daveyplate/better-auth-ui";
|
||||||
import { authViewPaths } from "@daveyplate/better-auth-ui/server";
|
import { authViewPaths } from "@daveyplate/better-auth-ui/server";
|
||||||
|
|
||||||
|
import { AuthViewProviders } from "@/components/providers";
|
||||||
|
|
||||||
export const dynamicParams = false;
|
export const dynamicParams = false;
|
||||||
|
|
||||||
export function generateStaticParams() {
|
export function generateStaticParams() {
|
||||||
@@ -16,7 +18,9 @@ export default async function AuthPage({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<main className="flex min-h-screen flex-col items-center justify-center p-4">
|
<main className="flex min-h-screen flex-col items-center justify-center p-4">
|
||||||
<AuthView path={path} />
|
<AuthViewProviders>
|
||||||
|
<AuthView path={path} />
|
||||||
|
</AuthViewProviders>
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
31
app/dashboard/layout.tsx
Normal file
31
app/dashboard/layout.tsx
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import * as Sentry from "@sentry/nextjs";
|
||||||
|
|
||||||
|
import { InitUser } from "@/components/init-user";
|
||||||
|
import { AppProviders } from "@/components/providers";
|
||||||
|
import { getAuthUser, getToken } from "@/lib/auth-server";
|
||||||
|
|
||||||
|
export default async function DashboardLayout({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}) {
|
||||||
|
const initialToken = await getToken();
|
||||||
|
const user = await getAuthUser();
|
||||||
|
|
||||||
|
if (user) {
|
||||||
|
const id = user.userId ?? String(user._id);
|
||||||
|
Sentry.setUser({
|
||||||
|
id,
|
||||||
|
email: user.email ?? undefined,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Sentry.setUser(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AppProviders initialToken={initialToken}>
|
||||||
|
<InitUser />
|
||||||
|
{children}
|
||||||
|
</AppProviders>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,12 +1,9 @@
|
|||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import Script from "next/script";
|
import Script from "next/script";
|
||||||
import { Manrope } from "next/font/google";
|
import { Manrope } from "next/font/google";
|
||||||
import * as Sentry from "@sentry/nextjs";
|
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { Providers } from "@/components/providers";
|
import { RootProviders } from "@/components/providers";
|
||||||
import { InitUser } from "@/components/init-user";
|
|
||||||
import { getAuthUser, getToken } from "@/lib/auth-server";
|
|
||||||
import { getLocale, getMessages, getTimeZone } from "next-intl/server";
|
import { getLocale, getMessages, getTimeZone } from "next-intl/server";
|
||||||
|
|
||||||
const manrope = Manrope({ subsets: ["latin"], variable: "--font-sans" });
|
const manrope = Manrope({ subsets: ["latin"], variable: "--font-sans" });
|
||||||
@@ -47,20 +44,9 @@ export default async function RootLayout({
|
|||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>) {
|
||||||
const initialToken = await getToken();
|
|
||||||
const locale = await getLocale();
|
const locale = await getLocale();
|
||||||
const messages = await getMessages();
|
const messages = await getMessages();
|
||||||
const timeZone = await getTimeZone();
|
const timeZone = await getTimeZone();
|
||||||
const user = await getAuthUser();
|
|
||||||
if (user) {
|
|
||||||
const id = user.userId ?? String(user._id);
|
|
||||||
Sentry.setUser({
|
|
||||||
id,
|
|
||||||
email: user.email ?? undefined,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
Sentry.setUser(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<html
|
<html
|
||||||
@@ -74,15 +60,9 @@ export default async function RootLayout({
|
|||||||
data-site-id="bb1ac546eda7"
|
data-site-id="bb1ac546eda7"
|
||||||
strategy="afterInteractive"
|
strategy="afterInteractive"
|
||||||
/>
|
/>
|
||||||
<Providers
|
<RootProviders locale={locale} messages={messages} timeZone={timeZone}>
|
||||||
initialToken={initialToken}
|
|
||||||
locale={locale}
|
|
||||||
messages={messages}
|
|
||||||
timeZone={timeZone}
|
|
||||||
>
|
|
||||||
<InitUser />
|
|
||||||
{children}
|
{children}
|
||||||
</Providers>
|
</RootProviders>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -34,21 +34,40 @@ function SentryAuthUserSync() {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Providers({
|
type RootProvidersProps = {
|
||||||
children,
|
|
||||||
initialToken,
|
|
||||||
locale,
|
|
||||||
messages,
|
|
||||||
timeZone,
|
|
||||||
}: {
|
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
initialToken?: string | null;
|
|
||||||
locale?: string;
|
locale?: string;
|
||||||
messages?: AbstractIntlMessages;
|
messages?: AbstractIntlMessages;
|
||||||
timeZone?: string;
|
timeZone?: string;
|
||||||
}) {
|
};
|
||||||
|
|
||||||
|
type AppProvidersProps = {
|
||||||
|
children: ReactNode;
|
||||||
|
initialToken?: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
function AuthUiShell({ children }: { children: ReactNode }) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AuthUIProvider
|
||||||
|
authClient={authClient}
|
||||||
|
navigate={router.push}
|
||||||
|
replace={router.replace}
|
||||||
|
onSessionChange={() => router.refresh()}
|
||||||
|
Link={Link}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</AuthUIProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RootProviders({
|
||||||
|
children,
|
||||||
|
locale,
|
||||||
|
messages,
|
||||||
|
timeZone,
|
||||||
|
}: RootProvidersProps) {
|
||||||
return (
|
return (
|
||||||
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
|
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
|
||||||
<NextIntlClientProvider
|
<NextIntlClientProvider
|
||||||
@@ -56,30 +75,34 @@ export function Providers({
|
|||||||
messages={messages}
|
messages={messages}
|
||||||
timeZone={timeZone}
|
timeZone={timeZone}
|
||||||
>
|
>
|
||||||
<ConvexBetterAuthProvider
|
{children}
|
||||||
client={convex}
|
|
||||||
authClient={authClient}
|
|
||||||
initialToken={initialToken}
|
|
||||||
>
|
|
||||||
<SentryAuthUserSync />
|
|
||||||
<AuthUIProvider
|
|
||||||
authClient={authClient}
|
|
||||||
navigate={router.push}
|
|
||||||
replace={router.replace}
|
|
||||||
onSessionChange={() => router.refresh()}
|
|
||||||
Link={Link}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
<GooeyToaster
|
|
||||||
position="bottom-right"
|
|
||||||
theme="dark"
|
|
||||||
visibleToasts={4}
|
|
||||||
maxQueue={8}
|
|
||||||
queueOverflow="drop-oldest"
|
|
||||||
/>
|
|
||||||
</AuthUIProvider>
|
|
||||||
</ConvexBetterAuthProvider>
|
|
||||||
</NextIntlClientProvider>
|
</NextIntlClientProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function AppProviders({ children, initialToken }: AppProvidersProps) {
|
||||||
|
return (
|
||||||
|
<ConvexBetterAuthProvider
|
||||||
|
client={convex}
|
||||||
|
authClient={authClient}
|
||||||
|
initialToken={initialToken}
|
||||||
|
>
|
||||||
|
<SentryAuthUserSync />
|
||||||
|
<AuthUiShell>
|
||||||
|
{children}
|
||||||
|
<GooeyToaster
|
||||||
|
position="bottom-right"
|
||||||
|
theme="dark"
|
||||||
|
visibleToasts={4}
|
||||||
|
maxQueue={8}
|
||||||
|
queueOverflow="drop-oldest"
|
||||||
|
/>
|
||||||
|
</AuthUiShell>
|
||||||
|
</ConvexBetterAuthProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function AuthViewProviders({ children }: { children: ReactNode }) {
|
||||||
|
return <AuthUiShell>{children}</AuthUiShell>;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user