setup done

This commit is contained in:
Om Lanke
2025-06-25 15:25:44 +05:30
parent ceb4b6b811
commit 2b777df5e2
55 changed files with 503 additions and 90 deletions

View File

@@ -1,16 +1,107 @@
import { Geist, Geist_Mono } from "next/font/google" import localFont from "next/font/local"
import "@workspace/ui/globals.css" import "@workspace/ui/globals.css"
import { Providers } from "@/components/providers" import { Providers } from "@/components/providers"
const fontSans = Geist({ const firaSans = localFont({
subsets: ["latin"], src: [
{
path: "../fonts/Fira-sans/FiraSans-Thin.ttf",
weight: "100",
style: "normal",
},
{
path: "../fonts/Fira-sans/FiraSans-ThinItalic.ttf",
weight: "100",
style: "italic",
},
{
path: "../fonts/Fira-sans/FiraSans-ExtraLight.ttf",
weight: "200",
style: "normal",
},
{
path: "../fonts/Fira-sans/FiraSans-ExtraLightItalic.ttf",
weight: "200",
style: "italic",
},
{
path: "../fonts/Fira-sans/FiraSans-Light.ttf",
weight: "300",
style: "normal",
},
{
path: "../fonts/Fira-sans/FiraSans-LightItalic.ttf",
weight: "300",
style: "italic",
},
{
path: "../fonts/Fira-sans/FiraSans-Regular.ttf",
weight: "400",
style: "normal",
},
{
path: "../fonts/Fira-sans/FiraSans-Italic.ttf",
weight: "400",
style: "italic",
},
{
path: "../fonts/Fira-sans/FiraSans-Medium.ttf",
weight: "500",
style: "normal",
},
{
path: "../fonts/Fira-sans/FiraSans-MediumItalic.ttf",
weight: "500",
style: "italic",
},
{
path: "../fonts/Fira-sans/FiraSans-SemiBold.ttf",
weight: "600",
style: "normal",
},
{
path: "../fonts/Fira-sans/FiraSans-SemiBoldItalic.ttf",
weight: "600",
style: "italic",
},
{
path: "../fonts/Fira-sans/FiraSans-Bold.ttf",
weight: "700",
style: "normal",
},
{
path: "../fonts/Fira-sans/FiraSans-BoldItalic.ttf",
weight: "700",
style: "italic",
},
{
path: "../fonts/Fira-sans/FiraSans-ExtraBold.ttf",
weight: "800",
style: "normal",
},
{
path: "../fonts/Fira-sans/FiraSans-ExtraBoldItalic.ttf",
weight: "800",
style: "italic",
},
{
path: "../fonts/Fira-sans/FiraSans-Black.ttf",
weight: "900",
style: "normal",
},
{
path: "../fonts/Fira-sans/FiraSans-BlackItalic.ttf",
weight: "900",
style: "italic",
},
],
variable: "--font-sans", variable: "--font-sans",
}) })
const fontMono = Geist_Mono({ const marcellus = localFont({
subsets: ["latin"], src: "../fonts/Marcellus/Marcellus-Regular.ttf",
variable: "--font-mono", variable: "--font-marcellus",
}) })
export default function RootLayout({ export default function RootLayout({
@@ -21,7 +112,7 @@ export default function RootLayout({
return ( return (
<html lang="en" suppressHydrationWarning> <html lang="en" suppressHydrationWarning>
<body <body
className={`${fontSans.variable} ${fontMono.variable} font-sans antialiased `} className={`${firaSans.variable} ${marcellus.variable} font-sans antialiased `}
> >
<Providers>{children}</Providers> <Providers>{children}</Providers>
</body> </body>

View File

@@ -1,11 +1,11 @@
import Login from "@/components/login"; import Login from "@/components/login";
import Studs from "@/components/studs"; import Studs from "@/components/studs";
import { db, students } from "@workspace/db"; import { db, admins } from "@workspace/db";
import { signIn, signOut } from "@workspace/auth"; import { auth, signIn, signOut } from "@workspace/auth";
async function getStudents() { async function getStudents() {
"use server"; "use server";
const s = await db.select().from(students); const s = await db.select().from(admins);
console.log(s); console.log(s);
} }
@@ -20,11 +20,12 @@ async function logOut() {
} }
export default async function Page() { export default async function Page() {
const session = await auth()
return ( return (
<div className="flex items-center justify-center min-h-svh"> <div className="flex items-center justify-center min-h-svh">
<div className="flex flex-col items-center justify-center gap-4"> <div className="flex flex-col items-center justify-center gap-4">
<h1 className="text-2xl font-bold">Hello admins</h1> <h1 className="text-2xl font-bold">Hello admins</h1>
<Login logIn={logIn} /> {!session?.user && <Login logIn={logIn} />}
<Studs action={getStudents} logOut={logOut} /> <Studs action={getStudents} logOut={logOut} />
</div> </div>
</div> </div>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1 +1,18 @@
export { auth as middleware } from "@workspace/auth"; import { auth } from "@workspace/auth";
import { NextResponse } from 'next/server';
export default auth((req: any) => {
// If the user is unauthenticated or an admin, allow the request.
if (!req.auth || req.auth.user?.role === "ADMIN") {
return NextResponse.next();
}
// Otherwise, redirect to the student app.
const studentUrl = process.env.STUDENT_URL ?? "http://localhost:3000"
return NextResponse.redirect(new URL(studentUrl, req.url));
}) as any;
export const config = {
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
}

19
apps/admin/next-auth.d.ts vendored Normal file
View File

@@ -0,0 +1,19 @@
import "next-auth";
declare module "next-auth" {
interface Session {
user: {
role?: "ADMIN" | "USER";
adminId?: number;
studentId?: number;
[key: string]: any;
};
}
}
declare module "next-auth/jwt" {
interface JWT {
role?: "ADMIN" | "USER";
adminId?: number;
studentId?: number;
}
}

View File

@@ -0,0 +1,2 @@
import { handlers } from "@workspace/auth";
export const { GET, POST } = handlers;

View File

@@ -1,16 +1,107 @@
import { Geist, Geist_Mono } from "next/font/google" import localFont from "next/font/local"
import "@workspace/ui/globals.css" import "@workspace/ui/globals.css"
import { Providers } from "@/components/providers" import { Providers } from "@/components/providers"
const fontSans = Geist({ const firaSans = localFont({
subsets: ["latin"], src: [
{
path: "../fonts/Fira-sans/FiraSans-Thin.ttf",
weight: "100",
style: "normal",
},
{
path: "../fonts/Fira-sans/FiraSans-ThinItalic.ttf",
weight: "100",
style: "italic",
},
{
path: "../fonts/Fira-sans/FiraSans-ExtraLight.ttf",
weight: "200",
style: "normal",
},
{
path: "../fonts/Fira-sans/FiraSans-ExtraLightItalic.ttf",
weight: "200",
style: "italic",
},
{
path: "../fonts/Fira-sans/FiraSans-Light.ttf",
weight: "300",
style: "normal",
},
{
path: "../fonts/Fira-sans/FiraSans-LightItalic.ttf",
weight: "300",
style: "italic",
},
{
path: "../fonts/Fira-sans/FiraSans-Regular.ttf",
weight: "400",
style: "normal",
},
{
path: "../fonts/Fira-sans/FiraSans-Italic.ttf",
weight: "400",
style: "italic",
},
{
path: "../fonts/Fira-sans/FiraSans-Medium.ttf",
weight: "500",
style: "normal",
},
{
path: "../fonts/Fira-sans/FiraSans-MediumItalic.ttf",
weight: "500",
style: "italic",
},
{
path: "../fonts/Fira-sans/FiraSans-SemiBold.ttf",
weight: "600",
style: "normal",
},
{
path: "../fonts/Fira-sans/FiraSans-SemiBoldItalic.ttf",
weight: "600",
style: "italic",
},
{
path: "../fonts/Fira-sans/FiraSans-Bold.ttf",
weight: "700",
style: "normal",
},
{
path: "../fonts/Fira-sans/FiraSans-BoldItalic.ttf",
weight: "700",
style: "italic",
},
{
path: "../fonts/Fira-sans/FiraSans-ExtraBold.ttf",
weight: "800",
style: "normal",
},
{
path: "../fonts/Fira-sans/FiraSans-ExtraBoldItalic.ttf",
weight: "800",
style: "italic",
},
{
path: "../fonts/Fira-sans/FiraSans-Black.ttf",
weight: "900",
style: "normal",
},
{
path: "../fonts/Fira-sans/FiraSans-BlackItalic.ttf",
weight: "900",
style: "italic",
},
],
variable: "--font-sans", variable: "--font-sans",
}) })
const fontMono = Geist_Mono({ const marcellus = localFont({
subsets: ["latin"], src: "../fonts/Marcellus/Marcellus-Regular.ttf",
variable: "--font-mono", variable: "--font-marcellus",
}) })
export default function RootLayout({ export default function RootLayout({
@@ -21,7 +112,7 @@ export default function RootLayout({
return ( return (
<html lang="en" suppressHydrationWarning> <html lang="en" suppressHydrationWarning>
<body <body
className={`${fontSans.variable} ${fontMono.variable} font-sans antialiased `} className={`${firaSans.variable} ${marcellus.variable} font-sans antialiased `}
> >
<Providers>{children}</Providers> <Providers>{children}</Providers>
</body> </body>

View File

@@ -1,11 +1,32 @@
import { Button } from "@workspace/ui/components/button"; import Login from "@/components/login";
import Studs from "@/components/studs";
import { db, admins } from "@workspace/db";
import { auth, signIn, signOut } from "@workspace/auth";
export default function Page() { async function getStudents() {
"use server";
const s = await db.select().from(admins);
console.log(s);
}
async function logIn() {
"use server";
await signIn("google");
}
async function logOut() {
"use server";
await signOut();
}
export default async function Page() {
const session = await auth()
return ( return (
<div className="flex items-center justify-center min-h-svh"> <div className="flex items-center justify-center min-h-svh">
<div className="flex flex-col items-center justify-center gap-4"> <div className="flex flex-col items-center justify-center gap-4">
<h1 className="text-2xl font-bold">Hello students</h1> <h1 className="text-2xl font-bold">Hello students</h1>
<Button size="sm">Button</Button> {!session?.user && <Login logIn={logIn} />}
<Studs action={getStudents} logOut={logOut} />
</div> </div>
</div> </div>
); );

View File

@@ -0,0 +1,25 @@
"use client";
import { signIn } from "@workspace/auth";
import { Button } from "@workspace/ui/components/button";
export default function Login({logIn}: {logIn: () => Promise<void>}) {
return (
<form action={logIn}>
<Button
type="submit"
variant="outline"
className="w-full h-12"
>
<div className="absolute inset-0 bg-gradient-to-r from-primary/0 via-primary/10 to-primary/0 translate-x-[-100%] group-hover:translate-x-[100%] transition-transform duration-700 ease-out pointer-events-none" />
<img
src="https://static.cdnlogo.com/logos/g/35/google-icon.svg"
alt="Google logo"
className="w-5 h-5 transition-transform duration-200"
/>
<span className="relative z-10 font-medium transition-colors duration-200 group-hover:text-foreground">
Sign in with Google
</span>
</Button>
</form>
);
}

View File

@@ -0,0 +1,19 @@
import { Button } from "@workspace/ui/components/button";
import { auth } from "@workspace/auth";
export default async function Studs({
action,
logOut,
}: {
action: () => void;
logOut: () => void;
}) {
const session = await auth();
if (!session?.user) return null;
return (
<div className="flex gap-2">
<Button onClick={action} variant="outline">Click me</Button>
<Button onClick={logOut}>Sign Out</Button>
</div>
);
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,18 @@
import { auth } from "@workspace/auth";
import { NextResponse } from 'next/server';
export default auth((req: any) => {
// If the user is unauthenticated or a student, allow the request.
if (!req.auth || req.auth.user?.role === "USER") {
return NextResponse.next();
}
// Otherwise, redirect to the admin app.
const adminURL = process.env.ADMIN_URL ?? "http://localhost:3001"
return NextResponse.redirect(new URL(adminURL, req.url));
}) as any;
export const config = {
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
}

20
apps/student/next-auth.d.ts vendored Normal file
View File

@@ -0,0 +1,20 @@
import "next-auth";
declare module "next-auth" {
interface Session {
user: {
role?: "ADMIN" | "USER";
adminId?: number;
studentId?: number;
[key: string]: any;
};
}
}
declare module "next-auth/jwt" {
interface JWT {
role?: "ADMIN" | "USER";
adminId?: number;
studentId?: number;
}
}

View File

@@ -1,9 +1,65 @@
import NextAuth, { type NextAuthConfig } from "next-auth"; import NextAuth, { type NextAuthConfig } from "next-auth";
import Google from "next-auth/providers/google"; import Google from "next-auth/providers/google";
import { db, admins, students } from "@workspace/db";
import { eq } from "drizzle-orm";
const authConfig: NextAuthConfig = { const authConfig: NextAuthConfig = {
providers: [Google], providers: [Google],
callbacks: {}, callbacks: {
async jwt({ token, account, user, profile }) {
// Only check DB on first sign in
if (account && user && user.email) {
const admin = await db
.select()
.from(admins)
.where(eq(admins.email, user.email))
.limit(1);
if (admin.length > 0 && admin[0]) {
token.role = "ADMIN";
token.adminId = admin[0].id;
} else {
token.role = "USER";
const student = await db
.select()
.from(students)
.where(eq(students.email, user.email))
.limit(1);
if (student.length > 0 && student[0]) {
token.studentId = student[0].id;
} else {
const nameParts = user.name?.split(" ") ?? [];
const firstName = nameParts[0] || "";
const lastName = nameParts.slice(1).join(" ") || "";
const newStudent = await db
.insert(students)
.values({
email: user.email,
firstName: firstName,
lastName: lastName,
profilePicture: user.image,
})
.returning({ id: students.id });
if (newStudent[0]) {
token.studentId = newStudent[0].id;
}
}
}
}
return token;
},
async session({ session, token }) {
if (token?.role) {
session.user.role = token.role as "ADMIN" | "USER";
}
if (token?.adminId) {
session.user.adminId = token.adminId as number;
}
if (token?.studentId) {
session.user.studentId = token.studentId as number;
}
return session;
},
},
}; };
const nextAuth = NextAuth(authConfig); const nextAuth = NextAuth(authConfig);

View File

@@ -12,7 +12,9 @@
"license": "ISC", "license": "ISC",
"packageManager": "pnpm@10.4.1", "packageManager": "pnpm@10.4.1",
"dependencies": { "dependencies": {
"next-auth": "5.0.0-beta.28" "next-auth": "5.0.0-beta.28",
"@workspace/db": "workspace:*",
"drizzle-orm": "^0.44.2"
}, },
"devDependencies": { "devDependencies": {
"dotenv": "^16.5.0" "dotenv": "^16.5.0"

20
packages/auth/types.d.ts vendored Normal file
View File

@@ -0,0 +1,20 @@
import "next-auth";
import "next-auth/jwt";
declare module "next-auth" {
interface Session {
user: {
role?: "ADMIN" | "USER";
adminId?: number;
studentId?: number;
[key: string]: any;
};
}
}
declare module "next-auth/jwt" {
interface JWT {
role?: "ADMIN" | "USER";
adminId?: number;
studentId?: number;
}
}

View File

@@ -10,11 +10,11 @@ const buttonVariants = cva(
variants: { variants: {
variant: { variant: {
default: default:
"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90", "bg-primary text-primary-foreground shadow-xs shadow-foreground/20 hover:bg-primary/90",
destructive: destructive:
"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40", "bg-destructive text-destructive-foreground shadow-xs shadow-foreground/20 hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
outline: outline:
"bg-background border border-border text-foreground shadow transition-all duration-300 ease-out group relative overflow-hidden hover:bg-muted hover:border-muted-foreground hover:shadow-lg hover:shadow-primary/20 hover:scale-102 active:scale-98 active:shadow-md focus:ring-2 focus:ring-primary focus:ring-offset-2", "bg-background border border-border text-foreground shadow shadow-foreground/20 transition-all duration-300 ease-out group relative overflow-hidden hover:bg-muted hover:border-muted-foreground hover:shadow-lg hover:shadow-primary/20 hover:scale-103 active:scale-98 active:shadow-md focus:ring-2 focus:ring-primary focus:ring-offset-2",
secondary: secondary:
"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80", "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground", ghost: "hover:bg-accent hover:text-accent-foreground",

View File

@@ -5,77 +5,82 @@
@import "tw-animate-css"; @import "tw-animate-css";
@theme {
--font-sans: "var(--font-sans)";
--font-marcellus: "var(--font-marcellus)";
}
@custom-variant dark (&:is(.dark *)); @custom-variant dark (&:is(.dark *));
:root { :root {
--background: oklch(1 0 0); --background: oklch(0.9889 0.004 286.33);
--foreground: oklch(0.145 0 0); --foreground: oklch(0.2442 0.006 0.59);
--card: oklch(1 0 0); --card: oklch(0.97 0.004 286.33);
--card-foreground: oklch(0.145 0 0); --card-foreground: oklch(0.2442 0.006 0.59);
--popover: oklch(1 0 0); --popover: oklch(1 0 0);
--popover-foreground: oklch(0.145 0 0); --popover-foreground: oklch(0.2442 0.006 0.59);
--primary: oklch(0.205 0 0); --primary: oklch(0.5044 0.184 22.51);
--primary-foreground: oklch(0.985 0 0); --primary-foreground: oklch(0.9889 0.004 286.33);
--secondary: oklch(0.97 0 0); --secondary: oklch(0.4605 0.005 271.31);
--secondary-foreground: oklch(0.205 0 0); --secondary-foreground: oklch(0.9889 0.004 286.33);
--muted: oklch(0.97 0 0); --muted: oklch(0.92 0.003 286.33);
--muted-foreground: oklch(0.556 0 0); --muted-foreground: oklch(0.44 0.004 286.33);
--accent: oklch(0.97 0 0); --accent: oklch(0.6034 0.234 27.23);
--accent-foreground: oklch(0.205 0 0); --accent-foreground: oklch(0.9889 0.004 286.33);
--destructive: oklch(0.577 0.245 27.325); --destructive: oklch(0.55 0.18 27.23);
--destructive-foreground: oklch(0.577 0.245 27.325); --destructive-foreground: oklch(0.9889 0.004 286.33);
--border: oklch(0.922 0 0); --border: oklch(0.88 0.003 286.33);
--input: oklch(0.922 0 0); --input: oklch(0.97 0.004 286.33);
--ring: oklch(0.708 0 0); --ring: oklch(0.6034 0.234 27.23);
--chart-1: oklch(0.646 0.222 41.116); --chart-1: oklch(0.5044 0.184 22.51);
--chart-2: oklch(0.6 0.118 184.704); --chart-2: oklch(0.6034 0.234 27.23);
--chart-3: oklch(0.398 0.07 227.392); --chart-3: oklch(0.4605 0.005 271.31);
--chart-4: oklch(0.828 0.189 84.429); --chart-4: oklch(0.7 0.15 120);
--chart-5: oklch(0.769 0.188 70.08); --chart-5: oklch(0.7 0.15 300);
--radius: 0.625rem; --radius: 0.625rem;
--sidebar: oklch(0.985 0 0); --sidebar: oklch(0.97 0.004 286.33);
--sidebar-foreground: oklch(0.145 0 0); --sidebar-foreground: oklch(0.2442 0.006 0.59);
--sidebar-primary: oklch(0.205 0 0); --sidebar-primary: oklch(0.5044 0.184 22.51);
--sidebar-primary-foreground: oklch(0.985 0 0); --sidebar-primary-foreground: oklch(0.9889 0.004 286.33);
--sidebar-accent: oklch(0.97 0 0); --sidebar-accent: oklch(0.6034 0.234 27.23);
--sidebar-accent-foreground: oklch(0.205 0 0); --sidebar-accent-foreground: oklch(0.9889 0.004 286.33);
--sidebar-border: oklch(0.922 0 0); --sidebar-border: oklch(0.88 0.003 286.33);
--sidebar-ring: oklch(0.708 0 0); --sidebar-ring: oklch(0.6034 0.234 27.23);
} }
.dark { .dark {
--background: oklch(0.145 0 0); --background: oklch(0.18 0.01 286.33);
--foreground: oklch(0.985 0 0); --foreground: oklch(0.9889 0.004 286.33);
--card: oklch(0.145 0 0); --card: oklch(0.22 0.01 286.33);
--card-foreground: oklch(0.985 0 0); --card-foreground: oklch(0.9889 0.004 286.33);
--popover: oklch(0.145 0 0); --popover: oklch(0.22 0.01 286.33);
--popover-foreground: oklch(0.985 0 0); --popover-foreground: oklch(0.9889 0.004 286.33);
--primary: oklch(0.985 0 0); --primary: oklch(0.7044 0.184 22.51);
--primary-foreground: oklch(0.205 0 0); --primary-foreground: oklch(0.18 0.01 286.33);
--secondary: oklch(0.269 0 0); --secondary: oklch(0.36 0.005 271.31);
--secondary-foreground: oklch(0.985 0 0); --secondary-foreground: oklch(0.9889 0.004 286.33);
--muted: oklch(0.269 0 0); --muted: oklch(0.25 0.01 286.33);
--muted-foreground: oklch(0.708 0 0); --muted-foreground: oklch(0.7 0.01 286.33);
--accent: oklch(0.269 0 0); --accent: oklch(0.8034 0.234 27.23);
--accent-foreground: oklch(0.985 0 0); --accent-foreground: oklch(0.18 0.01 286.33);
--destructive: oklch(0.396 0.141 25.723); --destructive: oklch(0.65 0.18 27.23);
--destructive-foreground: oklch(0.637 0.237 25.331); --destructive-foreground: oklch(0.18 0.01 286.33);
--border: oklch(0.269 0 0); --border: oklch(0.25 0.01 286.33);
--input: oklch(0.269 0 0); --input: oklch(0.22 0.01 286.33);
--ring: oklch(0.556 0 0); --ring: oklch(0.8034 0.234 27.23);
--chart-1: oklch(0.488 0.243 264.376); --chart-1: oklch(0.7044 0.184 22.51);
--chart-2: oklch(0.696 0.17 162.48); --chart-2: oklch(0.8034 0.234 27.23);
--chart-3: oklch(0.769 0.188 70.08); --chart-3: oklch(0.36 0.005 271.31);
--chart-4: oklch(0.627 0.265 303.9); --chart-4: oklch(0.7 0.15 120);
--chart-5: oklch(0.645 0.246 16.439); --chart-5: oklch(0.7 0.15 300);
--sidebar: oklch(0.205 0 0); --sidebar: oklch(0.22 0.01 286.33);
--sidebar-foreground: oklch(0.985 0 0); --sidebar-foreground: oklch(0.9889 0.004 286.33);
--sidebar-primary: oklch(0.488 0.243 264.376); --sidebar-primary: oklch(0.7044 0.184 22.51);
--sidebar-primary-foreground: oklch(0.985 0 0); --sidebar-primary-foreground: oklch(0.18 0.01 286.33);
--sidebar-accent: oklch(0.269 0 0); --sidebar-accent: oklch(0.8034 0.234 27.23);
--sidebar-accent-foreground: oklch(0.985 0 0); --sidebar-accent-foreground: oklch(0.18 0.01 286.33);
--sidebar-border: oklch(0.269 0 0); --sidebar-border: oklch(0.25 0.01 286.33);
--sidebar-ring: oklch(0.439 0 0); --sidebar-ring: oklch(0.8034 0.234 27.23);
} }
@theme inline { @theme inline {

6
pnpm-lock.yaml generated
View File

@@ -130,6 +130,12 @@ importers:
packages/auth: packages/auth:
dependencies: dependencies:
'@workspace/db':
specifier: workspace:*
version: link:../db
drizzle-orm:
specifier: ^0.44.2
version: 0.44.2(@neondatabase/serverless@1.0.1)(@types/pg@8.15.4)
next-auth: next-auth:
specifier: 5.0.0-beta.28 specifier: 5.0.0-beta.28
version: 5.0.0-beta.28(next@15.3.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0) version: 5.0.0-beta.28(next@15.3.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)