From 0f36eab6ca5e2da63c304c000cfaa9fed2b5f50d Mon Sep 17 00:00:00 2001 From: mzhang Date: Mon, 29 Jun 2026 17:27:58 -0500 Subject: [PATCH 01/12] init --- apps/app-portal/src/lib/auth/email-transport.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/apps/app-portal/src/lib/auth/email-transport.ts b/apps/app-portal/src/lib/auth/email-transport.ts index 4814ab98..ae334433 100644 --- a/apps/app-portal/src/lib/auth/email-transport.ts +++ b/apps/app-portal/src/lib/auth/email-transport.ts @@ -1 +1,17 @@ //Nodemailer transport stub for magic-link emails + +import EmailProvider from "next-auth/providers/email"; + +const config = EmailProvider({ + server: { + host: process.env.EMAIL_SERVER_HOST, + port: process.env.EMAIL_SERVER_PORT, + auth: { + user: process.env.EMAIL_SERVER_USER, + pass: process.env.EMAIL_SERVER_PASSWORD + } + }, + from: process.env.EMAIL_FROM, +}) + +export default config; \ No newline at end of file From da501d6d52b54e9c161aea3294ddc75bfea89ecc Mon Sep 17 00:00:00 2001 From: mzhang Date: Mon, 29 Jun 2026 17:37:49 -0500 Subject: [PATCH 02/12] init --- apps/app-portal/package.json | 2 ++ .../app-portal/src/app/(applicant)/layout.tsx | 24 +++++++++++++++---- apps/app-portal/src/lib/auth/[...nextauth].ts | 10 ++++++++ .../src/lib/auth/email-transport.ts | 8 +++---- 4 files changed, 35 insertions(+), 9 deletions(-) create mode 100644 apps/app-portal/src/lib/auth/[...nextauth].ts diff --git a/apps/app-portal/package.json b/apps/app-portal/package.json index c10898e1..8b8f5514 100644 --- a/apps/app-portal/package.json +++ b/apps/app-portal/package.json @@ -26,6 +26,8 @@ "lucide-react": "^1.14.0", "mongodb": "^7.2.0", "next": "^14.2.3", + "next-auth": "^4.24.14", + "nodemailer": "^9.0.1", "react": "^18.2.0", "react-day-picker": "^10.0.1", "react-dom": "^18.2.0", diff --git a/apps/app-portal/src/app/(applicant)/layout.tsx b/apps/app-portal/src/app/(applicant)/layout.tsx index 321362b2..9a2d4421 100644 --- a/apps/app-portal/src/app/(applicant)/layout.tsx +++ b/apps/app-portal/src/app/(applicant)/layout.tsx @@ -20,24 +20,38 @@ export default function ApplicantLayout({
{"HBP - HackBeanpot Applicant Portal + + HackBeanpot Applicant Portal +
- + Application diff --git a/apps/app-portal/src/lib/auth/[...nextauth].ts b/apps/app-portal/src/lib/auth/[...nextauth].ts new file mode 100644 index 00000000..899e9a74 --- /dev/null +++ b/apps/app-portal/src/lib/auth/[...nextauth].ts @@ -0,0 +1,10 @@ +import NextAuth from "next-auth" +import MainEmailProvider from "./email-transport.ts"; + +export const authOptions = { + providers: [ + MainEmailProvider + ], +} + +export default NextAuth(authOptions); \ No newline at end of file diff --git a/apps/app-portal/src/lib/auth/email-transport.ts b/apps/app-portal/src/lib/auth/email-transport.ts index ae334433..905a145c 100644 --- a/apps/app-portal/src/lib/auth/email-transport.ts +++ b/apps/app-portal/src/lib/auth/email-transport.ts @@ -8,10 +8,10 @@ const config = EmailProvider({ port: process.env.EMAIL_SERVER_PORT, auth: { user: process.env.EMAIL_SERVER_USER, - pass: process.env.EMAIL_SERVER_PASSWORD - } + pass: process.env.EMAIL_SERVER_PASSWORD, + }, }, from: process.env.EMAIL_FROM, -}) +}); -export default config; \ No newline at end of file +export default config; From 23f682eac44f9402b58b26f6ee90ac92b2266eb9 Mon Sep 17 00:00:00 2001 From: mzhang Date: Mon, 29 Jun 2026 17:38:13 -0500 Subject: [PATCH 03/12] init # Conflicts: # apps/app-portal/src/lib/auth/email-transport.ts --- apps/app-portal/src/lib/auth/email-transport.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/app-portal/src/lib/auth/email-transport.ts b/apps/app-portal/src/lib/auth/email-transport.ts index 905a145c..9b59d13a 100644 --- a/apps/app-portal/src/lib/auth/email-transport.ts +++ b/apps/app-portal/src/lib/auth/email-transport.ts @@ -11,7 +11,7 @@ const config = EmailProvider({ pass: process.env.EMAIL_SERVER_PASSWORD, }, }, - from: process.env.EMAIL_FROM, + from: process.env.EMAIL_FROM }); export default config; From f46ad0cf7c6e2c1ee436859cd058779d53cfa863 Mon Sep 17 00:00:00 2001 From: mzhang Date: Mon, 29 Jun 2026 17:38:56 -0500 Subject: [PATCH 04/12] init --- apps/app-portal/src/lib/auth/email-transport.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/app-portal/src/lib/auth/email-transport.ts b/apps/app-portal/src/lib/auth/email-transport.ts index 9b59d13a..905a145c 100644 --- a/apps/app-portal/src/lib/auth/email-transport.ts +++ b/apps/app-portal/src/lib/auth/email-transport.ts @@ -11,7 +11,7 @@ const config = EmailProvider({ pass: process.env.EMAIL_SERVER_PASSWORD, }, }, - from: process.env.EMAIL_FROM + from: process.env.EMAIL_FROM, }); export default config; From 2b9db892a96bfee0550c84dbb2a334ebe3fc5b42 Mon Sep 17 00:00:00 2001 From: mzhang Date: Mon, 29 Jun 2026 17:41:01 -0500 Subject: [PATCH 05/12] init --- apps/app-portal/src/lib/auth/[...nextauth].ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/app-portal/src/lib/auth/[...nextauth].ts b/apps/app-portal/src/lib/auth/[...nextauth].ts index 899e9a74..c0aaf1a6 100644 --- a/apps/app-portal/src/lib/auth/[...nextauth].ts +++ b/apps/app-portal/src/lib/auth/[...nextauth].ts @@ -4,7 +4,7 @@ import MainEmailProvider from "./email-transport.ts"; export const authOptions = { providers: [ MainEmailProvider - ], + ] } export default NextAuth(authOptions); \ No newline at end of file From 6eb8bb78393692adb33136f5b348520d79e7d20a Mon Sep 17 00:00:00 2001 From: mzhang Date: Thu, 2 Jul 2026 19:37:51 -0500 Subject: [PATCH 06/12] proper setup adjustment + db save --- apps/app-portal/package.json | 2 + .../src/app/api/auth/[...nextauth]/route.ts | 11 +-- apps/app-portal/src/lib/auth/[...nextauth].ts | 10 --- apps/app-portal/src/lib/auth/adapter.ts | 6 ++ apps/app-portal/src/lib/auth/config.ts | 28 +++++++ .../src/lib/auth/email-template.html | 51 ++++++++++++ .../src/lib/auth/email-transport.ts | 79 ++++++++++++++++++- apps/app-portal/src/lib/db.ts | 3 + 8 files changed, 170 insertions(+), 20 deletions(-) delete mode 100644 apps/app-portal/src/lib/auth/[...nextauth].ts create mode 100644 apps/app-portal/src/lib/auth/email-template.html diff --git a/apps/app-portal/package.json b/apps/app-portal/package.json index 8b8f5514..67d18e27 100644 --- a/apps/app-portal/package.json +++ b/apps/app-portal/package.json @@ -12,6 +12,7 @@ "dependencies": { "@google-cloud/storage": "^7.19.0", "@hookform/resolvers": "^5.2.2", + "@next-auth/mongodb-adapter": "^1.1.3", "@radix-ui/react-checkbox": "^1.3.3", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-label": "^2.1.8", @@ -46,6 +47,7 @@ "@repo/tailwind-config": "*", "@repo/typescript-config": "*", "@types/node": "^20.11.24", + "@types/nodemailer": "^8.0.1", "@types/react": "^18.2.61", "@types/react-dom": "^18.2.19", "autoprefixer": "^10.4.18", diff --git a/apps/app-portal/src/app/api/auth/[...nextauth]/route.ts b/apps/app-portal/src/app/api/auth/[...nextauth]/route.ts index 43e963af..e4241dc9 100644 --- a/apps/app-portal/src/app/api/auth/[...nextauth]/route.ts +++ b/apps/app-portal/src/app/api/auth/[...nextauth]/route.ts @@ -1,10 +1,7 @@ //NextAuth handler, email provider + Mongo adapter wired up -import { NextResponse } from "next/server"; +import NextAuth from "next-auth"; +import { authOptions } from "@/lib/auth/config"; -export async function GET() { - return NextResponse.json({ error: "not implemented" }, { status: 501 }); -} +const handler = NextAuth(authOptions); -export async function POST() { - return NextResponse.json({ error: "not implemented" }, { status: 501 }); -} +export { handler as GET, handler as POST }; diff --git a/apps/app-portal/src/lib/auth/[...nextauth].ts b/apps/app-portal/src/lib/auth/[...nextauth].ts deleted file mode 100644 index c0aaf1a6..00000000 --- a/apps/app-portal/src/lib/auth/[...nextauth].ts +++ /dev/null @@ -1,10 +0,0 @@ -import NextAuth from "next-auth" -import MainEmailProvider from "./email-transport.ts"; - -export const authOptions = { - providers: [ - MainEmailProvider - ] -} - -export default NextAuth(authOptions); \ No newline at end of file diff --git a/apps/app-portal/src/lib/auth/adapter.ts b/apps/app-portal/src/lib/auth/adapter.ts index 99ffe3d6..efaad463 100644 --- a/apps/app-portal/src/lib/auth/adapter.ts +++ b/apps/app-portal/src/lib/auth/adapter.ts @@ -1 +1,7 @@ //Mongo adapter instance +import { MongoDBAdapter } from "@next-auth/mongodb-adapter"; +import { mongoClientPromise } from "@/lib/db"; + +export const authAdapter = MongoDBAdapter(mongoClientPromise, { + databaseName: process.env.MONGO_SERVER_DBNAME, +}); diff --git a/apps/app-portal/src/lib/auth/config.ts b/apps/app-portal/src/lib/auth/config.ts index 455732a2..832b8ed8 100644 --- a/apps/app-portal/src/lib/auth/config.ts +++ b/apps/app-portal/src/lib/auth/config.ts @@ -1 +1,29 @@ //NextAuth options (providers, callbacks, session strategy) + +import type { NextAuthOptions } from "next-auth"; +import MainEmailProvider from "./email-transport"; +import { authAdapter } from "./adapter"; + +export const authOptions: NextAuthOptions = { + adapter: authAdapter, + providers: [MainEmailProvider], + secret: process.env.NEXTAUTH_SECRET, + session: { strategy: "jwt" }, + pages: { + // signIn: "/login", // point at a custom sign-in page once you build one + }, + callbacks: { + async jwt({ token, user }) { + if (user) { + token.id = user.id; + } + return token; + }, + async session({ session, token }) { + if (session.user) { + (session.user as { id?: string }).id = token.id as string; + } + return session; + }, + }, +}; diff --git a/apps/app-portal/src/lib/auth/email-template.html b/apps/app-portal/src/lib/auth/email-template.html new file mode 100644 index 00000000..0b6467d6 --- /dev/null +++ b/apps/app-portal/src/lib/auth/email-template.html @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + +
+ + HackBeanpot +
+ Click the button below to sign in to the HackBeanpot application portal. +
+ + + + +
+ + Sign in to HackBeanpot + +
+
+ + Or copy and paste this link into your browser:
+ {{url}} +
+ If you did not request this email you can safely ignore it. +
+ diff --git a/apps/app-portal/src/lib/auth/email-transport.ts b/apps/app-portal/src/lib/auth/email-transport.ts index 905a145c..06be6559 100644 --- a/apps/app-portal/src/lib/auth/email-transport.ts +++ b/apps/app-portal/src/lib/auth/email-transport.ts @@ -1,17 +1,90 @@ -//Nodemailer transport stub for magic-link emails - import EmailProvider from "next-auth/providers/email"; +import type { SendVerificationRequestParams } from "next-auth/providers/email"; + +import { createTransport } from "nodemailer" +import {Theme} from "next-auth"; +import { readFileSync } from "fs"; +import { join } from "path"; + +const TEMPLATE_PATH = join(process.cwd(), "src/lib/auth/email-template.html"); + +async function customRequest(params: SendVerificationRequestParams) { + const { identifier, url, provider, theme } = params + const { host } = new URL(url) + const transport = createTransport(provider.server) + const result = await transport.sendMail({ + to: identifier, + from: provider.from, + subject: `Sign in to ${host}`, + text: text({ url, host }), + html: html({ url, host, theme }), + }) + const failed = result.rejected.concat(result.pending).filter(Boolean) + if (failed.length) { + throw new Error(`Email(s) (${failed.join(", ")}) could not be sent`) + } +} + +/** + * Email HTML body + * Insert invisible space into domains from being turned into a hyperlink by email + * clients like Outlook and Apple mail, as this is confusing because it seems + * like they are supposed to click on it to sign in. + * + * @note We don't add the email address to avoid needing to escape it, if you do, remember to sanitize it! + */ +function html(params: { url: string, host: string, theme: Theme }) { + const { url, theme } = params + + const brandColor = theme.brandColor || "#346df1" + const color = { + background: "#f9f9f9", + text: "#444", + mainBackground: "#fff", + buttonBackground: brandColor, + buttonBorder: brandColor, + buttonText: theme.buttonText || "#fff", + } + + // Logo is served from /public; use an absolute URL so email clients can load it. + const logoUrl = `${process.env.NEXTAUTH_URL ?? ""}/email_logo.png` + + const replacements: Record = { + url, + logoUrl, + background: color.background, + mainBackground: color.mainBackground, + textColor: color.text, + buttonBackground: color.buttonBackground, + buttonBorder: color.buttonBorder, + buttonText: color.buttonText, + } + + let template = readFileSync(TEMPLATE_PATH, "utf8") + for (const [key, value] of Object.entries(replacements)) { + template = template.replaceAll(`{{${key}}}`, value) + } + return template +} + +/** Email Text body (fallback for email clients that don't render HTML, e.g. feature phones) */ +function text({ url, host }: { url: string, host: string }) { + return `Sign in to ${host}\n${url}\n\n` +} const config = EmailProvider({ server: { host: process.env.EMAIL_SERVER_HOST, - port: process.env.EMAIL_SERVER_PORT, + port: Number(process.env.EMAIL_SERVER_PORT), auth: { user: process.env.EMAIL_SERVER_USER, pass: process.env.EMAIL_SERVER_PASSWORD, }, }, from: process.env.EMAIL_FROM, + sendVerificationRequest(params) { + return customRequest(params) + }, }); export default config; diff --git a/apps/app-portal/src/lib/db.ts b/apps/app-portal/src/lib/db.ts index ccb5ed42..e671d2b3 100644 --- a/apps/app-portal/src/lib/db.ts +++ b/apps/app-portal/src/lib/db.ts @@ -27,3 +27,6 @@ export async function getDb(): Promise { const connectedClient = await clientPromise; return connectedClient.db(dbName); } + +// need client promise for the NextAuth MongoDB adapter +export const mongoClientPromise = clientPromise; From dbd5cb8dcb5bad12d8251cb0a4b093222eabd909 Mon Sep 17 00:00:00 2001 From: mzhang Date: Thu, 2 Jul 2026 19:52:44 -0500 Subject: [PATCH 07/12] session validation checkers --- apps/app-portal/src/lib/auth/guards.ts | 18 ++++++++++++++++++ apps/app-portal/src/lib/auth/session.ts | 6 ++++++ apps/app-portal/src/middleware.ts | 22 +++++++++++++++------- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/apps/app-portal/src/lib/auth/guards.ts b/apps/app-portal/src/lib/auth/guards.ts index 0ceda79a..087b4384 100644 --- a/apps/app-portal/src/lib/auth/guards.ts +++ b/apps/app-portal/src/lib/auth/guards.ts @@ -1 +1,19 @@ //requireUser() and requireAdmin() helpers for route handlers +import { getSession } from "./session"; + +export async function requireUser() { + const session = await getSession(); + if (!session?.user) { + throw new Error("Unauthorized"); + } + return session.user; +} + +export async function requireAdmin() { + const user = await requireUser(); + // if (!(user as { isAdmin?: boolean }).isAdmin) { + // throw new Error("Forbidden"); + // } + //TODO: finish admin role + return user; +} diff --git a/apps/app-portal/src/lib/auth/session.ts b/apps/app-portal/src/lib/auth/session.ts index a2f7175e..5da3f41a 100644 --- a/apps/app-portal/src/lib/auth/session.ts +++ b/apps/app-portal/src/lib/auth/session.ts @@ -1 +1,7 @@ //server-side getSession() helper for RSCs +import { getServerSession } from "next-auth"; +import { authOptions } from "./config"; + +export function getSession() { + return getServerSession(authOptions); +} diff --git a/apps/app-portal/src/middleware.ts b/apps/app-portal/src/middleware.ts index 7ae3dd9f..3c00a676 100644 --- a/apps/app-portal/src/middleware.ts +++ b/apps/app-portal/src/middleware.ts @@ -1,12 +1,20 @@ //Next middleware, redirects unauthed users from protected routes -import { NextResponse } from "next/server"; -// import type { NextRequest } from "next/server"; -export default function middleware() { - //_request: NextRequest - return NextResponse.next(); -} +//Middleware intercepts at every requests and is a preliminary check to whether a user is authorized to visit a page +// or not. The protected pages matched by the regex represent pages that should be always available to public without +// having needed to login in advance. +//Unauthenticated requests to matched routes are redirected to sign-in +//the matcher was written with assistance of AI export const config = { - matcher: [], + matcher: [ + /* + * Protect everything EXCEPT: + * - /api/auth/* NextAuth's own endpoints (must stay public) + * - /_next/static,/_next/image, /favicon.ico build/static assets + * - the landing page "/" and /login public entry points + * Add any other public path to this negative lookahead as you build it. + */ + "/((?!api/auth|_next/static|_next/image|favicon.ico|login$|$).*)", + ], }; From ac73cbf39871d2fb98020e2a8d325fc2a8daf5a2 Mon Sep 17 00:00:00 2001 From: mzhang Date: Tue, 7 Jul 2026 19:32:45 -0500 Subject: [PATCH 08/12] working jwt's, logging for debug impl --- apps/app-portal/package.json | 2 +- apps/app-portal/public/email_logo.png | Bin 2118 -> 107722 bytes .../app/{api => }/auth/[...nextauth]/route.ts | 0 apps/app-portal/src/app/providers.tsx | 28 ++- .../src/components/auth/SignInForm.tsx | 25 +- .../src/components/auth/UserMenu.tsx | 2 +- apps/app-portal/src/lib/auth/adapter.ts | 35 ++- apps/app-portal/src/lib/auth/config.ts | 55 ++++- .../src/lib/auth/email-template.html | 25 +- .../src/lib/auth/email-transport.ts | 47 +++- apps/app-portal/src/lib/auth/log.ts | 47 ++++ apps/app-portal/src/middleware.ts | 18 +- yarn.lock | 231 ++++++++++++++---- 13 files changed, 423 insertions(+), 92 deletions(-) rename apps/app-portal/src/app/{api => }/auth/[...nextauth]/route.ts (100%) create mode 100644 apps/app-portal/src/lib/auth/log.ts diff --git a/apps/app-portal/package.json b/apps/app-portal/package.json index 67d18e27..83221262 100644 --- a/apps/app-portal/package.json +++ b/apps/app-portal/package.json @@ -25,7 +25,7 @@ "clsx": "^2.1.1", "date-fns": "^4.4.0", "lucide-react": "^1.14.0", - "mongodb": "^7.2.0", + "mongodb": "^5.9.2", "next": "^14.2.3", "next-auth": "^4.24.14", "nodemailer": "^9.0.1", diff --git a/apps/app-portal/public/email_logo.png b/apps/app-portal/public/email_logo.png index ab7f6d4abd95ec6468e33565b3232217ad6b60de..ee5cf205f89e5e7690ef19c0b6ecbe4450f4aed0 100644 GIT binary patch literal 107722 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

;$I6=q`b!gKhV7-9vDnDenAwl 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 diff --git a/apps/app-portal/src/app/api/auth/[...nextauth]/route.ts b/apps/app-portal/src/app/auth/[...nextauth]/route.ts similarity index 100% rename from apps/app-portal/src/app/api/auth/[...nextauth]/route.ts rename to apps/app-portal/src/app/auth/[...nextauth]/route.ts diff --git a/apps/app-portal/src/app/providers.tsx b/apps/app-portal/src/app/providers.tsx index 118beb8b..42580b14 100644 --- a/apps/app-portal/src/app/providers.tsx +++ b/apps/app-portal/src/app/providers.tsx @@ -1,16 +1,36 @@ "use client"; import useIsMobile from "@repo/util/hooks/useIsMobile"; -import React, { createContext } from "react"; +import { SessionProvider } from "next-auth/react"; +import { usePathname } from "next/navigation"; +import React, { createContext, useEffect } from "react"; +import { authLog } from "@/lib/auth/log"; export const MobileContext = createContext({ isMobile: false }); export function Providers({ children }: { children: React.ReactNode }) { const isMobile = useIsMobile(); + const pathname = usePathname(); + + // Frontend trace: which path the browser is on + whether an auth cookie exists. + useEffect(() => { + const hasSessionCookie = document.cookie + .split("; ") + .some( + (c) => + c.startsWith("next-auth.session-token") || + c.startsWith("__Secure-next-auth.session-token"), + ); + authLog("client", `navigated → ${pathname}`, { hasSessionCookie }); + }, [pathname]); return ( - - {children} - + // basePath MUST match the auth route location (/auth). Without this, the + // next-auth/react client (signIn/signOut/useSession) posts to /api/auth → 404. + + + {children} + + ); } diff --git a/apps/app-portal/src/components/auth/SignInForm.tsx b/apps/app-portal/src/components/auth/SignInForm.tsx index 25def937..b1420929 100644 --- a/apps/app-portal/src/components/auth/SignInForm.tsx +++ b/apps/app-portal/src/components/auth/SignInForm.tsx @@ -1,6 +1,7 @@ //email input form, calls signIn("email") import React, { useEffect, useState } from "react"; import Image from "next/image"; +import { signIn } from "next-auth/react"; import icon from "@/app/icon.ico"; import { Toaster } from "@/components/ui/sonner"; import { toast } from "sonner"; @@ -32,21 +33,15 @@ export function SignInForm() { setStatus("loading"); try { - //TODO: wire to the real endpoint - const res = await fetch("/api/auth/signin/email", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ email: email.trim() }), + // signIn() handles CSRF, form-encoding, and the redirect for us. + // redirect:false → we drive the UI state ourselves instead of navigating. + const res = await signIn("email", { + email: email.trim(), + redirect: false, + callbackUrl: "/", }); - // rate-limit -> toast - if (res.status === 429) { - toast.error("Too many attempts. Please wait a minute and try again."); - setStatus("idle"); - return; - } - - if (!res.ok) { + if (res?.error) { toast.error( "Something went wrong sending your sign-in link. Please try again.", ); @@ -56,7 +51,7 @@ export function SignInForm() { setStatus("sent"); } catch { - // network failure (fetch threw err) + // network failure (signIn threw) toast.error("Network error. Check your connection and try again."); setStatus("idle"); } @@ -69,7 +64,7 @@ export function SignInForm() { {/*icon*/} HBP Logo {/*title*/} -

HackBeanpot

+

Login to HackBeanpot!

{/*input area*/}
diff --git a/apps/app-portal/src/components/auth/UserMenu.tsx b/apps/app-portal/src/components/auth/UserMenu.tsx index c4c41079..e1fc2040 100644 --- a/apps/app-portal/src/components/auth/UserMenu.tsx +++ b/apps/app-portal/src/components/auth/UserMenu.tsx @@ -41,7 +41,7 @@ export default function UserMenu({ email }: UserMenuProps): JSX.Element { async function handleSignOut() { setOpen(false); // TODO: wire to NextAuth — signOut({ callbackUrl: "/" }) once next-auth is installed. - await fetch("/api/auth/signout", { method: "POST" }).catch(() => {}); + await fetch("/auth/signout", { method: "POST" }).catch(() => {}); window.location.href = "/"; } diff --git a/apps/app-portal/src/lib/auth/adapter.ts b/apps/app-portal/src/lib/auth/adapter.ts index efaad463..1d50ce6b 100644 --- a/apps/app-portal/src/lib/auth/adapter.ts +++ b/apps/app-portal/src/lib/auth/adapter.ts @@ -1,7 +1,40 @@ //Mongo adapter instance import { MongoDBAdapter } from "@next-auth/mongodb-adapter"; +import type { Adapter } from "next-auth/adapters"; import { mongoClientPromise } from "@/lib/db"; +import { authLog, redact } from "./log"; -export const authAdapter = MongoDBAdapter(mongoClientPromise, { +// Stores users, accounts, sessions, and the magic-link verification tokens +// that EmailProvider depends on. +const baseAdapter = MongoDBAdapter(mongoClientPromise, { databaseName: process.env.MONGO_SERVER_DBNAME, }); + +// Wrap every adapter method so each DB operation in the auth flow is logged. +// The two that matter most for magic-link debugging: +// • createVerificationToken → the temp token is WRITTEN to Mongo (at sign-in) +// • useVerificationToken → the temp token is READ + CONSUMED (on link click) +function withLogging(adapter: Adapter): Adapter { + const wrapped: Record = {}; + for (const key of Object.keys(adapter) as (keyof Adapter)[]) { + const fn = adapter[key]; + if (typeof fn !== "function") { + wrapped[key] = fn; + continue; + } + wrapped[key] = async (...args: unknown[]) => { + authLog("adapter", `→ ${key}`, args.map(redact)); + try { + const result = await (fn as (...a: unknown[]) => Promise)(...args); + authLog("adapter", `✓ ${key}`, redact(result)); + return result; + } catch (err) { + authLog("adapter", `✗ ${key} threw: ${(err as Error).message}`); + throw err; + } + }; + } + return wrapped as Adapter; +} + +export const authAdapter = withLogging(baseAdapter); diff --git a/apps/app-portal/src/lib/auth/config.ts b/apps/app-portal/src/lib/auth/config.ts index 832b8ed8..b796e0da 100644 --- a/apps/app-portal/src/lib/auth/config.ts +++ b/apps/app-portal/src/lib/auth/config.ts @@ -3,26 +3,79 @@ import type { NextAuthOptions } from "next-auth"; import MainEmailProvider from "./email-transport"; import { authAdapter } from "./adapter"; +import { authLog, mask } from "./log"; export const authOptions: NextAuthOptions = { adapter: authAdapter, providers: [MainEmailProvider], secret: process.env.NEXTAUTH_SECRET, session: { strategy: "jwt" }, + + // NextAuth's own verbose logging (routes hit, errors) in dev. + debug: process.env.NODE_ENV !== "production", + // Route NextAuth's internal logs through our prefixed logger. + logger: { + error(code, metadata) { + authLog("event", `NextAuth ERROR: ${code}`, metadata); + }, + warn(code) { + authLog("event", `NextAuth warn: ${code}`); + }, + debug(code, metadata) { + authLog("event", `NextAuth debug: ${code}`, metadata); + }, + }, + + // Lifecycle events — the clearest high-level trace of the flow. + events: { + async signIn({ user, isNewUser }) { + authLog("event", `signIn OK: ${user.email}`, { isNewUser }); + }, + async signOut() { + authLog("event", "signOut"); + }, + async createUser({ user }) { + authLog("event", `createUser: ${user.email}`, { id: user.id }); + }, + async session({ session }) { + authLog("event", `session read: ${session.user?.email ?? "(anon)"}`); + }, + }, + pages: { - // signIn: "/login", // point at a custom sign-in page once you build one + signIn: "/auth/signin", + verifyRequest: "/auth/verify-request", + error: "/auth/error", }, + callbacks: { + // Gatekeeper: log every sign-in attempt (return false here to reject one). + async signIn({ user, email }) { + authLog("callback", `signIn attempt: ${user?.email ?? "(unknown)"}`, { + verificationRequest: email?.verificationRequest ?? false, + }); + return true; + }, + // Runs when the JWT (the cookie's contents) is created/updated. async jwt({ token, user }) { if (user) { token.id = user.id; } + authLog("callback", `jwt: building token for ${token.email ?? "(none)"}`, { + id: token.id, + sub: token.sub, + jti: mask(token.jti as string), + }); return token; }, + // Runs when app code reads the session; shapes what the app sees. async session({ session, token }) { if (session.user) { (session.user as { id?: string }).id = token.id as string; } + authLog("callback", `session: exposing ${session.user?.email ?? "(none)"}`, { + id: (session.user as { id?: string })?.id, + }); return session; }, }, diff --git a/apps/app-portal/src/lib/auth/email-template.html b/apps/app-portal/src/lib/auth/email-template.html index 0b6467d6..0795cba9 100644 --- a/apps/app-portal/src/lib/auth/email-template.html +++ b/apps/app-portal/src/lib/auth/email-template.html @@ -5,25 +5,24 @@ it must come from the `url` param, never be hardcoded. --> - +
- - -
+ - HackBeanpot + HackBeanpot
+ Click the button below to sign in to the HackBeanpot application portal.
- +
+ - - - diff --git a/apps/app-portal/src/lib/auth/email-transport.ts b/apps/app-portal/src/lib/auth/email-transport.ts index 06be6559..f2ba4a15 100644 --- a/apps/app-portal/src/lib/auth/email-transport.ts +++ b/apps/app-portal/src/lib/auth/email-transport.ts @@ -5,23 +5,48 @@ import { createTransport } from "nodemailer" import {Theme} from "next-auth"; import { readFileSync } from "fs"; import { join } from "path"; +import { authLog, mask } from "./log"; const TEMPLATE_PATH = join(process.cwd(), "src/lib/auth/email-template.html"); async function customRequest(params: SendVerificationRequestParams) { const { identifier, url, provider, theme } = params const { host } = new URL(url) - const transport = createTransport(provider.server) - const result = await transport.sendMail({ - to: identifier, + const token = new URL(url).searchParams.get("token") + + authLog("email", `sending magic link → ${identifier}`, { + host, from: provider.from, - subject: `Sign in to ${host}`, - text: text({ url, host }), - html: html({ url, host, theme }), + token: mask(token), }) - const failed = result.rejected.concat(result.pending).filter(Boolean) - if (failed.length) { - throw new Error(`Email(s) (${failed.join(", ")}) could not be sent`) + // DEV AID: the full clickable link. Since email delivery is flaky, you can + // copy this straight from the terminal and paste it in the browser to sign in. + authLog("email", `magic link URL (dev): ${url}`) + + const transport = createTransport(provider.server) + try { + const result = await transport.sendMail({ + to: identifier, + from: provider.from, + subject: `Verify your identity for HackBeanpot`, + text: text({ url, host }), + html: html({ url, host, theme }), + }) + authLog("email", `SMTP responded for ${identifier}`, { + messageId: result.messageId, + accepted: result.accepted, + rejected: result.rejected, + response: result.response, + }) + const failed = result.rejected.concat(result.pending).filter(Boolean) + if (failed.length) { + authLog("email", `✗ SMTP rejected recipient(s): ${failed.join(", ")}`) + throw new Error(`Email(s) (${failed.join(", ")}) could not be sent`) + } + authLog("email", `✓ accepted by SMTP for ${identifier}`) + } catch (err) { + authLog("email", `✗ sendMail threw: ${(err as Error).message}`) + throw err } } @@ -47,7 +72,9 @@ function html(params: { url: string, host: string, theme: Theme }) { } // Logo is served from /public; use an absolute URL so email clients can load it. - const logoUrl = `${process.env.NEXTAUTH_URL ?? ""}/email_logo.png` + // Derive the origin (NEXTAUTH_URL may carry an /auth path we must strip). + const origin = new URL(process.env.NEXTAUTH_URL ?? "http://localhost:3000").origin + const logoUrl = `${origin}/email_logo.png` const replacements: Record = { url, diff --git a/apps/app-portal/src/lib/auth/log.ts b/apps/app-portal/src/lib/auth/log.ts new file mode 100644 index 00000000..2e0ce64f --- /dev/null +++ b/apps/app-portal/src/lib/auth/log.ts @@ -0,0 +1,47 @@ +// Lightweight auth-flow logger. +// Every log is prefixed `[auth:]` and timestamped so you can grep the +// whole magic-link flow across server + client: grep "\[auth:" in your terminal. +// +// On by default in development. Set AUTH_DEBUG=false to silence in dev, or +// AUTH_DEBUG=true to force it on in production. + +type Scope = + | "email" // sending the magic-link email + | "adapter" // MongoDB reads/writes (users, sessions, verification tokens) + | "callback" // signIn / jwt / session callbacks + | "event" // NextAuth lifecycle events + | "middleware" // backend edge requests + | "client"; // frontend navigation + +const ENABLED = + process.env.AUTH_DEBUG === "true" || + (process.env.AUTH_DEBUG !== "false" && process.env.NODE_ENV !== "production"); + +export function authLog(scope: Scope, msg: string, data?: unknown) { + if (!ENABLED) return; + const line = `${new Date().toISOString()} [auth:${scope}] ${msg}`; + if (data !== undefined) { + // eslint-disable-next-line no-console + console.log(line, data); + } else { + // eslint-disable-next-line no-console + console.log(line); + } +} + +// Show enough of a token/secret to correlate log lines without dumping the whole thing. +export function mask(value?: string | null): string { + if (!value) return "(none)"; + if (value.length <= 8) return `${value.slice(0, 1)}***`; + return `${value.slice(0, 4)}…${value.slice(-4)} (len ${value.length})`; +} + +// Shallow-copy an object, masking any token-ish fields, for safe logging. +export function redact(obj: T): T | Record { + if (!obj || typeof obj !== "object") return obj; + const out: Record = {}; + for (const [k, v] of Object.entries(obj as Record)) { + out[k] = k === "token" || k === "sessionToken" ? mask(v as string) : v; + } + return out; +} diff --git a/apps/app-portal/src/middleware.ts b/apps/app-portal/src/middleware.ts index 3c00a676..37014b94 100644 --- a/apps/app-portal/src/middleware.ts +++ b/apps/app-portal/src/middleware.ts @@ -5,6 +5,22 @@ // having needed to login in advance. //Unauthenticated requests to matched routes are redirected to sign-in +import { NextResponse } from "next/server"; +import type { NextRequest } from "next/server"; +import { authLog } from "@/lib/auth/log"; + +export default function middleware(request: NextRequest) { + const { pathname, search } = request.nextUrl; + // JWT session cookie name differs by protocol (Secure prefix over HTTPS). + const hasSessionCookie = + request.cookies.has("next-auth.session-token") || + request.cookies.has("__Secure-next-auth.session-token"); + authLog("middleware", `hit ${pathname}${search}`, { + authenticated: hasSessionCookie, + }); + return NextResponse.next(); +} + //the matcher was written with assistance of AI export const config = { matcher: [ @@ -15,6 +31,6 @@ export const config = { * - the landing page "/" and /login public entry points * Add any other public path to this negative lookahead as you build it. */ - "/((?!api/auth|_next/static|_next/image|favicon.ico|login$|$).*)", + "/((?!auth|_next/static|_next/image|favicon.ico|login$|$).*)", ], }; diff --git a/yarn.lock b/yarn.lock index afa1b5ec..2807ab7b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -133,6 +133,11 @@ dependencies: "@babel/types" "^7.28.5" +"@babel/runtime@^7.20.13": + version "7.29.7" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.29.7.tgz#12022450c45a4da6d8d8287b18a4ff2ddb23f768" + integrity sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw== + "@babel/template@^7.25.9", "@babel/template@^7.27.2": version "7.27.2" resolved "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz" @@ -442,13 +447,18 @@ resolved "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz" integrity sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug== -"@mongodb-js/saslprep@^1.3.0": - version "1.4.11" - resolved "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.4.11.tgz" - integrity sha512-o9rAHc0IpIjuPSxRutWpE1F62x7n+4mVS4rCNHkzhIUMQcc18bb6xEq5wd2NdN0WjepIyXIppRshYI2kQDOZVA== +"@mongodb-js/saslprep@^1.1.0": + version "1.4.12" + resolved "https://registry.yarnpkg.com/@mongodb-js/saslprep/-/saslprep-1.4.12.tgz#919ed57f24bb0a9087963fc6e94ee24c37fe08a9" + integrity sha512-QAfAMwNgnYxZ2C6D1HgeP7Gc4i/uvJRim415PCIL9ptRxWMNbWeLBYb2/9R4pGKny/s1FVu2JA2cxCUBUOggrA== dependencies: sparse-bitfield "^3.0.3" +"@next-auth/mongodb-adapter@^1.1.3": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@next-auth/mongodb-adapter/-/mongodb-adapter-1.1.3.tgz#531b75f828338ebd73d8539685641a17804d1d77" + integrity sha512-nH/may8hntYBlcuxepSsR2b95w6SRnP+c/FFt3KKjdTScNjhrN0zZdlT90nisjG/3gK+MvzMbz/F4Rwpgr9RMA== + "@next/env@14.2.35": version "14.2.35" resolved "https://registry.npmjs.org/@next/env/-/env-14.2.35.tgz" @@ -485,7 +495,6 @@ "@next/swc-linux-arm64-musl@14.2.33": version "14.2.33" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.33.tgz#dc8903469e5c887b25e3c2217a048bd30c58d3d4" resolved "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.33.tgz" integrity sha512-Bm+QulsAItD/x6Ih8wGIMfRJy4G73tu1HJsrccPW6AfqdZd0Sfm5Imhgkgq2+kly065rYMnCOxTBvmvFY1BKfg== @@ -552,6 +561,11 @@ resolved "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz" integrity sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA== +"@panva/hkdf@^1.0.2": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@panva/hkdf/-/hkdf-1.2.1.tgz#cb0d111ef700136f4580349ff0226bf25c853f23" + integrity sha512-6oclG6Y3PiDFcoyk8srjLfVKyMfVCKJ27JwNPViuXziFpmdz+MZnZN/aKY0JGXgYuO/VghU0jcOAZgWXZ1Dmrw== + "@pkgjs/parseargs@^0.11.0": version "0.11.0" resolved "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz" @@ -798,13 +812,6 @@ "@radix-ui/react-use-previous" "1.1.1" "@radix-ui/react-use-size" "1.1.1" -"@radix-ui/react-slot@1.2.4", "@radix-ui/react-slot@^1.2.4": - version "1.2.4" - resolved "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz" - integrity sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA== - dependencies: - "@radix-ui/react-compose-refs" "1.1.2" - "@radix-ui/react-use-callback-ref@1.1.1": version "1.1.1" resolved "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz" @@ -1008,6 +1015,13 @@ dependencies: undici-types "~6.19.2" +"@types/nodemailer@^8.0.1": + version "8.0.1" + resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-8.0.1.tgz#4ef2b4e62c819225a0b8a6384bf750c0c664d465" + integrity sha512-PxpaInm8V1JQDd4j0ds5HfvWQk8JupS1C0Picb96QJsrrRDjBH+DlK7L4ZdNSqNULhiZRQHc40nLVShaGxXAMw== + dependencies: + "@types/node" "*" + "@types/normalize-package-data@^2.4.0": version "2.4.4" resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz" @@ -1061,11 +1075,12 @@ resolved "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz" integrity sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA== -"@types/whatwg-url@^13.0.0": - version "13.0.0" - resolved "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-13.0.0.tgz" - integrity sha512-N8WXpbE6Wgri7KUSvrmQcqrMllKZ9uxkYWMt+mCSGwNc0Hsw9VQTW7ApqI4XNrx6/SaM2QQJCzMPDEXE058s+Q== +"@types/whatwg-url@^8.2.1": + version "8.2.2" + resolved "https://registry.yarnpkg.com/@types/whatwg-url/-/whatwg-url-8.2.2.tgz#749d5b3873e845897ada99be4448041d4cc39e63" + integrity sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA== dependencies: + "@types/node" "*" "@types/webidl-conversions" "*" "@typescript-eslint/eslint-plugin@8.23.0", "@typescript-eslint/eslint-plugin@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0": @@ -1606,10 +1621,10 @@ browserslist@^4.23.3, browserslist@^4.24.0, browserslist@^4.24.3: node-releases "^2.0.19" update-browserslist-db "^1.1.1" -bson@^7.2.0: - version "7.2.0" - resolved "https://registry.npmjs.org/bson/-/bson-7.2.0.tgz" - integrity sha512-YCEo7KjMlbNlyHhz7zAZNDpIpQbd+wOEHJYezv0nMYTn4x31eIUM2yomNNubclAt63dObUzKHWsBLJ9QcZNSnQ== +bson@^5.5.0: + version "5.5.1" + resolved "https://registry.yarnpkg.com/bson/-/bson-5.5.1.tgz#f5849d405711a7f23acdda9a442375df858e6833" + integrity sha512-ix0EwukN2EpC0SRWIj/7B5+A6uQMQy6KMREI9qQqvgpkV2frH63T0UDVd1SYedL6dNCmDBYB3QtXi4ISk9YT+g== buffer-equal-constant-time@^1.0.1: version "1.0.1" @@ -1755,6 +1770,11 @@ convert-source-map@^2.0.0: resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== +cookie@^0.7.0: + version "0.7.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" + integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== + core-js-compat@^3.34.0: version "3.40.0" resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.40.0.tgz" @@ -1884,6 +1904,11 @@ data-view-byte-offset@^1.0.1: es-errors "^1.3.0" is-data-view "^1.0.1" +date-fns@^4.1.0, date-fns@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-4.4.0.tgz#806539edf45c616b2b76b5f78b88c56ed3c7e036" + integrity sha512-+1UMbeh68lH1SegH83CGWwpb6OHHbpSgr3+s5Eww5M4CAgswBpoWS0AjTOfEJ33HiYKz1hdj/KTFprzXHmq/6w== + debug@4, debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.7: version "4.4.0" resolved "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz" @@ -3055,6 +3080,11 @@ internal-slot@^1.1.0: resolved "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz" integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg== +ip-address@^10.1.1: + version "10.2.0" + resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-10.2.0.tgz#805fc178b20c518bd4c8548b24fe30892d7f3206" + integrity sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA== + is-array-buffer@^3.0.4, is-array-buffer@^3.0.5: version "3.0.5" resolved "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz" @@ -3323,6 +3353,11 @@ jju@~1.4.0: resolved "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz" integrity sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA== +jose@^4.15.5, jose@^4.15.9: + version "4.15.9" + resolved "https://registry.yarnpkg.com/jose/-/jose-4.15.9.tgz#9b68eda29e9a0614c042fa29387196c7dd800100" + integrity sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA== + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" @@ -3491,6 +3526,13 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + lucide-react@^1.14.0: version "1.16.0" resolved "https://registry.npmjs.org/lucide-react/-/lucide-react-1.16.0.tgz" @@ -3565,22 +3607,24 @@ minimist@^1.2.0, minimist@^1.2.6: resolved "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz" integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== -mongodb-connection-string-url@^7.0.0: - version "7.0.1" - resolved "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-7.0.1.tgz" - integrity sha512-h0AZ9A7IDVwwHyMxmdMXKy+9oNlF0zFoahHiX3vQ8e3KFcSP3VmsmfvtRSuLPxmyv2vjIDxqty8smTgie/SNRQ== +mongodb-connection-string-url@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz#57901bf352372abdde812c81be47b75c6b2ec5cf" + integrity sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ== dependencies: - "@types/whatwg-url" "^13.0.0" - whatwg-url "^14.1.0" + "@types/whatwg-url" "^8.2.1" + whatwg-url "^11.0.0" -mongodb@^7.2.0: - version "7.2.0" - resolved "https://registry.npmjs.org/mongodb/-/mongodb-7.2.0.tgz" - integrity sha512-F/2+BMZtLVhY30ioZp0dAmZ+IRZMBqI+nrv6t5+9/1AIwCa8sMRC3jBf81lpxMhnZgqq8CoUD503Z1oZWq1/sw== +mongodb@^5.9.2: + version "5.9.2" + resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-5.9.2.tgz#39a73b9fbc87ac9d9c1aaf8aab5c5bb69e2b913e" + integrity sha512-H60HecKO4Bc+7dhOv4sJlgvenK4fQNqqUIlXxZYQNbfEWSALGAwGoyJd/0Qwk4TttFXUOHJ2ZJQe/52ScaUwtQ== dependencies: - "@mongodb-js/saslprep" "^1.3.0" - bson "^7.2.0" - mongodb-connection-string-url "^7.0.0" + bson "^5.5.0" + mongodb-connection-string-url "^2.6.0" + socks "^2.7.1" + optionalDependencies: + "@mongodb-js/saslprep" "^1.1.0" ms@^2.1.1, ms@^2.1.3: version "2.1.3" @@ -3606,6 +3650,21 @@ natural-compare@^1.4.0: resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== +next-auth@^4.24.14: + version "4.24.14" + resolved "https://registry.yarnpkg.com/next-auth/-/next-auth-4.24.14.tgz#c14916e215f8f4aef2358e694bd14c40212139b2" + integrity sha512-YRz6xFDXKUwiXSMMChbrBEWyFktZ1qZXEgeSHQQ3nsy08B4c/xLk6REeutRsIFwkjY/1+ShHnu07DN3JeJguig== + dependencies: + "@babel/runtime" "^7.20.13" + "@panva/hkdf" "^1.0.2" + cookie "^0.7.0" + jose "^4.15.5" + oauth "^0.9.15" + openid-client "^5.4.0" + preact "^10.6.3" + preact-render-to-string "^5.1.19" + uuid "^8.3.2" + next@^14.2.3: version "14.2.35" resolved "https://registry.npmjs.org/next/-/next-14.2.35.tgz" @@ -3641,6 +3700,11 @@ node-releases@^2.0.19: resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz" integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== +nodemailer@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-9.0.1.tgz#871c04d8423fc0c790289f4a8f6f71f1b3563e8c" + integrity sha512-Gwv8SQewT616ZM/URn0H54b8PWo/Wum7md3EW2aWy1lO27+WZCX+Xyak3J+NlmHUjDh5ME+uesJUDRbR3Ye8Bw== + normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz" @@ -3661,11 +3725,21 @@ normalize-range@^0.1.2: resolved "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz" integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== +oauth@^0.9.15: + version "0.9.15" + resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1" + integrity sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA== + object-assign@^4.0.1, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== +object-hash@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5" + integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw== + object-hash@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz" @@ -3731,6 +3805,11 @@ object.values@^1.1.6, object.values@^1.2.0, object.values@^1.2.1: define-properties "^1.2.1" es-object-atoms "^1.0.0" +oidc-token-hash@^5.0.3: + version "5.2.0" + resolved "https://registry.yarnpkg.com/oidc-token-hash/-/oidc-token-hash-5.2.0.tgz#be8a8885c7e2478d21a674e15afa31f1bcc4a61f" + integrity sha512-6gj2m8cJZ+iSW8bm0FXdGF0YhIQbKrfP4yWTNzxc31U6MOjfEmB1rHvlYvxI1B7t7BCi1F2vYTT6YhtQRG4hxw== + once@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" @@ -3738,6 +3817,16 @@ once@^1.4.0: dependencies: wrappy "1" +openid-client@^5.4.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/openid-client/-/openid-client-5.7.1.tgz#34cace862a3e6472ed7d0a8616ef73b7fb85a9c3" + integrity sha512-jDBPgSVfTnkIh71Hg9pRvtJc6wTwqjRkN88+gCFtYWrlP4Yx2Dsrow8uPi3qLr/aeymPF3o2+dS+wOpglK04ew== + dependencies: + jose "^4.15.9" + lru-cache "^6.0.0" + object-hash "^2.2.0" + oidc-token-hash "^5.0.3" + optionator@^0.9.3: version "0.9.4" resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz" @@ -3944,6 +4033,18 @@ postcss@^8.4.35, postcss@^8.4.47: picocolors "^1.1.1" source-map-js "^1.2.1" +preact-render-to-string@^5.1.19: + version "5.2.6" + resolved "https://registry.yarnpkg.com/preact-render-to-string/-/preact-render-to-string-5.2.6.tgz#0ff0c86cd118d30affb825193f18e92bd59d0604" + integrity sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw== + dependencies: + pretty-format "^3.8.0" + +preact@^10.6.3: + version "10.29.3" + resolved "https://registry.yarnpkg.com/preact/-/preact-10.29.3.tgz#36f96b7a8edc2fccea76daa5e7545597dc15ab28" + integrity sha512-D9NL1GAnJZhc3RndVs4gDdxEeU9TcHgywMrhhOsnpdlvFjdbx0gAsLUnH6JEhlJH5giL7Tx5biWPUSEXE/HPzw== + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" @@ -3967,6 +4068,11 @@ prettier@^3.2.5: resolved "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz" integrity sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ== +pretty-format@^3.8.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-3.8.0.tgz#bfbed56d5e9a776645f4b1ff7aa1a3ac4fa3c385" + integrity sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew== + prop-types@^15.8.1: version "15.8.1" resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz" @@ -3976,7 +4082,7 @@ prop-types@^15.8.1: object-assign "^4.1.1" react-is "^16.13.1" -punycode@^2.1.0, punycode@^2.3.1: +punycode@^2.1.0, punycode@^2.1.1: version "2.3.1" resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== @@ -3986,6 +4092,14 @@ queue-microtask@^1.2.2: resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +react-day-picker@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/react-day-picker/-/react-day-picker-10.0.1.tgz#8498e3f0ace2e9d03c209a5458c451a377c2d85c" + integrity sha512-eNh6BlwcYInWaJtRv18mXQ06Ys/H6rdTZAnTaSdOYJuTpwP1JMCHNd1FDRadA+gbeinq+psdULN5Xnowy9mV8w== + dependencies: + "@date-fns/tz" "^1.4.1" + date-fns "^4.1.0" + react-dom@^18.2.0: version "18.3.1" resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz" @@ -3994,6 +4108,15 @@ react-dom@^18.2.0: loose-envify "^1.1.0" scheduler "^0.23.2" +react-dropzone@^15.0.0: + version "15.0.0" + resolved "https://registry.yarnpkg.com/react-dropzone/-/react-dropzone-15.0.0.tgz#bd03c7c2b14fe4ea9db1a9c74502b85339f2e505" + integrity sha512-lGjYV/EoqEjEWPnmiSvH4v5IoIAwQM2W4Z1C0Q/Pw2xD0eVzKPS359BQTUMum+1fa0kH2nrKjuavmTPOGhpLPg== + dependencies: + attr-accept "^2.2.4" + file-selector "^2.1.0" + prop-types "^15.8.1" + react-hook-form@^7.75.0: version "7.76.0" resolved "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.76.0.tgz" @@ -4373,6 +4496,19 @@ slash@^3.0.0: resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +smart-buffer@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" + integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== + +socks@^2.7.1: + version "2.8.9" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.8.9.tgz#aa5f130ca0f88a43fa44faf4869c50d22aa27752" + integrity sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw== + dependencies: + ip-address "^10.1.1" + smart-buffer "^4.2.0" + sonner@^2.0.7: version "2.0.7" resolved "https://registry.npmjs.org/sonner/-/sonner-2.0.7.tgz" @@ -4735,12 +4871,12 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -tr46@^5.1.0: - version "5.1.1" - resolved "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz" - integrity sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw== +tr46@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-3.0.0.tgz#555c4e297a950617e8eeddef633c87d4d9d6cbf9" + integrity sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA== dependencies: - punycode "^2.3.1" + punycode "^2.1.1" tr46@~0.0.3: version "0.0.3" @@ -4979,7 +5115,7 @@ uuid@^14.0.0: resolved "https://registry.npmjs.org/uuid/-/uuid-14.0.0.tgz" integrity sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg== -uuid@^8.0.0: +uuid@^8.0.0, uuid@^8.3.2: version "8.3.2" resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== @@ -5027,12 +5163,12 @@ webidl-conversions@^7.0.0: resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz" integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== -whatwg-url@^14.1.0: - version "14.2.0" - resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz" - integrity sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw== +whatwg-url@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-11.0.0.tgz#0a849eebb5faf2119b901bb76fd795c2848d4018" + integrity sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ== dependencies: - tr46 "^5.1.0" + tr46 "^3.0.0" webidl-conversions "^7.0.0" whatwg-url@^5.0.0: @@ -5140,6 +5276,11 @@ yallist@^3.0.2: resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + yaml@^2.3.4: version "2.7.0" resolved "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz" From 489d7dd7bd5b6ea59bd2ff7df9d61f815d250973 Mon Sep 17 00:00:00 2001 From: mzhang Date: Tue, 7 Jul 2026 19:37:26 -0500 Subject: [PATCH 09/12] removed excessive logging --- apps/app-portal/src/app/providers.tsx | 17 +------ apps/app-portal/src/lib/auth/adapter.ts | 33 +------------ apps/app-portal/src/lib/auth/config.ts | 47 +------------------ .../src/lib/auth/email-transport.ts | 42 ++++------------- apps/app-portal/src/lib/auth/log.ts | 47 ------------------- apps/app-portal/src/middleware.ts | 12 +---- 6 files changed, 14 insertions(+), 184 deletions(-) delete mode 100644 apps/app-portal/src/lib/auth/log.ts diff --git a/apps/app-portal/src/app/providers.tsx b/apps/app-portal/src/app/providers.tsx index 42580b14..7a7b0128 100644 --- a/apps/app-portal/src/app/providers.tsx +++ b/apps/app-portal/src/app/providers.tsx @@ -2,27 +2,12 @@ import useIsMobile from "@repo/util/hooks/useIsMobile"; import { SessionProvider } from "next-auth/react"; -import { usePathname } from "next/navigation"; -import React, { createContext, useEffect } from "react"; -import { authLog } from "@/lib/auth/log"; +import React, { createContext } from "react"; export const MobileContext = createContext({ isMobile: false }); export function Providers({ children }: { children: React.ReactNode }) { const isMobile = useIsMobile(); - const pathname = usePathname(); - - // Frontend trace: which path the browser is on + whether an auth cookie exists. - useEffect(() => { - const hasSessionCookie = document.cookie - .split("; ") - .some( - (c) => - c.startsWith("next-auth.session-token") || - c.startsWith("__Secure-next-auth.session-token"), - ); - authLog("client", `navigated → ${pathname}`, { hasSessionCookie }); - }, [pathname]); return ( // basePath MUST match the auth route location (/auth). Without this, the diff --git a/apps/app-portal/src/lib/auth/adapter.ts b/apps/app-portal/src/lib/auth/adapter.ts index 1d50ce6b..9f3e1617 100644 --- a/apps/app-portal/src/lib/auth/adapter.ts +++ b/apps/app-portal/src/lib/auth/adapter.ts @@ -1,40 +1,9 @@ //Mongo adapter instance import { MongoDBAdapter } from "@next-auth/mongodb-adapter"; -import type { Adapter } from "next-auth/adapters"; import { mongoClientPromise } from "@/lib/db"; -import { authLog, redact } from "./log"; // Stores users, accounts, sessions, and the magic-link verification tokens // that EmailProvider depends on. -const baseAdapter = MongoDBAdapter(mongoClientPromise, { +export const authAdapter = MongoDBAdapter(mongoClientPromise, { databaseName: process.env.MONGO_SERVER_DBNAME, }); - -// Wrap every adapter method so each DB operation in the auth flow is logged. -// The two that matter most for magic-link debugging: -// • createVerificationToken → the temp token is WRITTEN to Mongo (at sign-in) -// • useVerificationToken → the temp token is READ + CONSUMED (on link click) -function withLogging(adapter: Adapter): Adapter { - const wrapped: Record = {}; - for (const key of Object.keys(adapter) as (keyof Adapter)[]) { - const fn = adapter[key]; - if (typeof fn !== "function") { - wrapped[key] = fn; - continue; - } - wrapped[key] = async (...args: unknown[]) => { - authLog("adapter", `→ ${key}`, args.map(redact)); - try { - const result = await (fn as (...a: unknown[]) => Promise)(...args); - authLog("adapter", `✓ ${key}`, redact(result)); - return result; - } catch (err) { - authLog("adapter", `✗ ${key} threw: ${(err as Error).message}`); - throw err; - } - }; - } - return wrapped as Adapter; -} - -export const authAdapter = withLogging(baseAdapter); diff --git a/apps/app-portal/src/lib/auth/config.ts b/apps/app-portal/src/lib/auth/config.ts index b796e0da..15e33534 100644 --- a/apps/app-portal/src/lib/auth/config.ts +++ b/apps/app-portal/src/lib/auth/config.ts @@ -3,7 +3,6 @@ import type { NextAuthOptions } from "next-auth"; import MainEmailProvider from "./email-transport"; import { authAdapter } from "./adapter"; -import { authLog, mask } from "./log"; export const authOptions: NextAuthOptions = { adapter: authAdapter, @@ -11,37 +10,6 @@ export const authOptions: NextAuthOptions = { secret: process.env.NEXTAUTH_SECRET, session: { strategy: "jwt" }, - // NextAuth's own verbose logging (routes hit, errors) in dev. - debug: process.env.NODE_ENV !== "production", - // Route NextAuth's internal logs through our prefixed logger. - logger: { - error(code, metadata) { - authLog("event", `NextAuth ERROR: ${code}`, metadata); - }, - warn(code) { - authLog("event", `NextAuth warn: ${code}`); - }, - debug(code, metadata) { - authLog("event", `NextAuth debug: ${code}`, metadata); - }, - }, - - // Lifecycle events — the clearest high-level trace of the flow. - events: { - async signIn({ user, isNewUser }) { - authLog("event", `signIn OK: ${user.email}`, { isNewUser }); - }, - async signOut() { - authLog("event", "signOut"); - }, - async createUser({ user }) { - authLog("event", `createUser: ${user.email}`, { id: user.id }); - }, - async session({ session }) { - authLog("event", `session read: ${session.user?.email ?? "(anon)"}`); - }, - }, - pages: { signIn: "/auth/signin", verifyRequest: "/auth/verify-request", @@ -49,11 +17,8 @@ export const authOptions: NextAuthOptions = { }, callbacks: { - // Gatekeeper: log every sign-in attempt (return false here to reject one). - async signIn({ user, email }) { - authLog("callback", `signIn attempt: ${user?.email ?? "(unknown)"}`, { - verificationRequest: email?.verificationRequest ?? false, - }); + // Gatekeeper: return false here to reject a sign-in. + async signIn() { return true; }, // Runs when the JWT (the cookie's contents) is created/updated. @@ -61,11 +26,6 @@ export const authOptions: NextAuthOptions = { if (user) { token.id = user.id; } - authLog("callback", `jwt: building token for ${token.email ?? "(none)"}`, { - id: token.id, - sub: token.sub, - jti: mask(token.jti as string), - }); return token; }, // Runs when app code reads the session; shapes what the app sees. @@ -73,9 +33,6 @@ export const authOptions: NextAuthOptions = { if (session.user) { (session.user as { id?: string }).id = token.id as string; } - authLog("callback", `session: exposing ${session.user?.email ?? "(none)"}`, { - id: (session.user as { id?: string })?.id, - }); return session; }, }, diff --git a/apps/app-portal/src/lib/auth/email-transport.ts b/apps/app-portal/src/lib/auth/email-transport.ts index f2ba4a15..a67cb2ea 100644 --- a/apps/app-portal/src/lib/auth/email-transport.ts +++ b/apps/app-portal/src/lib/auth/email-transport.ts @@ -5,48 +5,24 @@ import { createTransport } from "nodemailer" import {Theme} from "next-auth"; import { readFileSync } from "fs"; import { join } from "path"; -import { authLog, mask } from "./log"; const TEMPLATE_PATH = join(process.cwd(), "src/lib/auth/email-template.html"); async function customRequest(params: SendVerificationRequestParams) { const { identifier, url, provider, theme } = params const { host } = new URL(url) - const token = new URL(url).searchParams.get("token") - authLog("email", `sending magic link → ${identifier}`, { - host, + const transport = createTransport(provider.server) + const result = await transport.sendMail({ + to: identifier, from: provider.from, - token: mask(token), + subject: `Verify your identity for HackBeanpot`, + text: text({ url, host }), + html: html({ url, host, theme }), }) - // DEV AID: the full clickable link. Since email delivery is flaky, you can - // copy this straight from the terminal and paste it in the browser to sign in. - authLog("email", `magic link URL (dev): ${url}`) - - const transport = createTransport(provider.server) - try { - const result = await transport.sendMail({ - to: identifier, - from: provider.from, - subject: `Verify your identity for HackBeanpot`, - text: text({ url, host }), - html: html({ url, host, theme }), - }) - authLog("email", `SMTP responded for ${identifier}`, { - messageId: result.messageId, - accepted: result.accepted, - rejected: result.rejected, - response: result.response, - }) - const failed = result.rejected.concat(result.pending).filter(Boolean) - if (failed.length) { - authLog("email", `✗ SMTP rejected recipient(s): ${failed.join(", ")}`) - throw new Error(`Email(s) (${failed.join(", ")}) could not be sent`) - } - authLog("email", `✓ accepted by SMTP for ${identifier}`) - } catch (err) { - authLog("email", `✗ sendMail threw: ${(err as Error).message}`) - throw err + const failed = result.rejected.concat(result.pending).filter(Boolean) + if (failed.length) { + throw new Error(`Email(s) (${failed.join(", ")}) could not be sent`) } } diff --git a/apps/app-portal/src/lib/auth/log.ts b/apps/app-portal/src/lib/auth/log.ts deleted file mode 100644 index 2e0ce64f..00000000 --- a/apps/app-portal/src/lib/auth/log.ts +++ /dev/null @@ -1,47 +0,0 @@ -// Lightweight auth-flow logger. -// Every log is prefixed `[auth:]` and timestamped so you can grep the -// whole magic-link flow across server + client: grep "\[auth:" in your terminal. -// -// On by default in development. Set AUTH_DEBUG=false to silence in dev, or -// AUTH_DEBUG=true to force it on in production. - -type Scope = - | "email" // sending the magic-link email - | "adapter" // MongoDB reads/writes (users, sessions, verification tokens) - | "callback" // signIn / jwt / session callbacks - | "event" // NextAuth lifecycle events - | "middleware" // backend edge requests - | "client"; // frontend navigation - -const ENABLED = - process.env.AUTH_DEBUG === "true" || - (process.env.AUTH_DEBUG !== "false" && process.env.NODE_ENV !== "production"); - -export function authLog(scope: Scope, msg: string, data?: unknown) { - if (!ENABLED) return; - const line = `${new Date().toISOString()} [auth:${scope}] ${msg}`; - if (data !== undefined) { - // eslint-disable-next-line no-console - console.log(line, data); - } else { - // eslint-disable-next-line no-console - console.log(line); - } -} - -// Show enough of a token/secret to correlate log lines without dumping the whole thing. -export function mask(value?: string | null): string { - if (!value) return "(none)"; - if (value.length <= 8) return `${value.slice(0, 1)}***`; - return `${value.slice(0, 4)}…${value.slice(-4)} (len ${value.length})`; -} - -// Shallow-copy an object, masking any token-ish fields, for safe logging. -export function redact(obj: T): T | Record { - if (!obj || typeof obj !== "object") return obj; - const out: Record = {}; - for (const [k, v] of Object.entries(obj as Record)) { - out[k] = k === "token" || k === "sessionToken" ? mask(v as string) : v; - } - return out; -} diff --git a/apps/app-portal/src/middleware.ts b/apps/app-portal/src/middleware.ts index 37014b94..abeb9d96 100644 --- a/apps/app-portal/src/middleware.ts +++ b/apps/app-portal/src/middleware.ts @@ -6,18 +6,8 @@ //Unauthenticated requests to matched routes are redirected to sign-in import { NextResponse } from "next/server"; -import type { NextRequest } from "next/server"; -import { authLog } from "@/lib/auth/log"; -export default function middleware(request: NextRequest) { - const { pathname, search } = request.nextUrl; - // JWT session cookie name differs by protocol (Secure prefix over HTTPS). - const hasSessionCookie = - request.cookies.has("next-auth.session-token") || - request.cookies.has("__Secure-next-auth.session-token"); - authLog("middleware", `hit ${pathname}${search}`, { - authenticated: hasSessionCookie, - }); +export default function middleware() { return NextResponse.next(); } From fa9bfc290747905bc755a3a2044c7a49e4245641 Mon Sep 17 00:00:00 2001 From: mzhang Date: Tue, 14 Jul 2026 10:25:00 -0500 Subject: [PATCH 10/12] redir to dashboard or admin based on email ext, added checks on admin page --- apps/app-portal/src/app/(admin)/layout.tsx | 22 ++++++++++--------- .../src/components/auth/SignInForm.tsx | 5 ++++- apps/app-portal/src/lib/auth/config.ts | 7 +++++- apps/app-portal/src/lib/auth/guards.ts | 7 +++--- apps/app-portal/src/lib/auth/roles.ts | 7 ++++++ 5 files changed, 32 insertions(+), 16 deletions(-) create mode 100644 apps/app-portal/src/lib/auth/roles.ts diff --git a/apps/app-portal/src/app/(admin)/layout.tsx b/apps/app-portal/src/app/(admin)/layout.tsx index 5ff60692..10552a96 100644 --- a/apps/app-portal/src/app/(admin)/layout.tsx +++ b/apps/app-portal/src/app/(admin)/layout.tsx @@ -2,24 +2,26 @@ import React from "react"; import UserMenu from "@/components/auth/UserMenu"; import AdminSidebar from "@/components/admin/AdminSidebar"; import { redirect } from "next/navigation"; - -// TODO: pull the real email from session later -const email = "admin@example.com"; - -async function requireAdmin(): Promise { - return true; -} +import { getSession } from "@/lib/auth/session"; export default async function AdminLayout({ children, }: { children: React.ReactNode; }) { - const isAdmin = await requireAdmin(); + const session = await getSession(); + const user = session?.user as + | { email?: string | null; isAdmin?: boolean } + | undefined; - if (!isAdmin) { - redirect("/"); + if (!user) { + redirect("/auth/signin"); } + if (!user.isAdmin) { + redirect("/dashboard"); + } + + const email = user.email ?? ""; return (
diff --git a/apps/app-portal/src/components/auth/SignInForm.tsx b/apps/app-portal/src/components/auth/SignInForm.tsx index b1420929..c99e6957 100644 --- a/apps/app-portal/src/components/auth/SignInForm.tsx +++ b/apps/app-portal/src/components/auth/SignInForm.tsx @@ -2,6 +2,7 @@ import React, { useEffect, useState } from "react"; import Image from "next/image"; import { signIn } from "next-auth/react"; +import { isAdminEmail } from "@/lib/auth/roles"; import icon from "@/app/icon.ico"; import { Toaster } from "@/components/ui/sonner"; import { toast } from "sonner"; @@ -35,10 +36,12 @@ export function SignInForm() { try { // signIn() handles CSRF, form-encoding, and the redirect for us. // redirect:false → we drive the UI state ourselves instead of navigating. + // The callbackUrl is baked into the magic link; the admin layout + // re-checks the role server-side, so this is routing, not authorization. const res = await signIn("email", { email: email.trim(), redirect: false, - callbackUrl: "/", + callbackUrl: isAdminEmail(email) ? "/admin" : "/dashboard", }); if (res?.error) { diff --git a/apps/app-portal/src/lib/auth/config.ts b/apps/app-portal/src/lib/auth/config.ts index 15e33534..54d41de9 100644 --- a/apps/app-portal/src/lib/auth/config.ts +++ b/apps/app-portal/src/lib/auth/config.ts @@ -3,6 +3,7 @@ import type { NextAuthOptions } from "next-auth"; import MainEmailProvider from "./email-transport"; import { authAdapter } from "./adapter"; +import { isAdminEmail } from "./roles"; export const authOptions: NextAuthOptions = { adapter: authAdapter, @@ -25,13 +26,17 @@ export const authOptions: NextAuthOptions = { async jwt({ token, user }) { if (user) { token.id = user.id; + token.isAdmin = isAdminEmail(user.email); } return token; }, // Runs when app code reads the session; shapes what the app sees. async session({ session, token }) { if (session.user) { - (session.user as { id?: string }).id = token.id as string; + (session.user as { id?: string; isAdmin?: boolean }).id = + token.id as string; + (session.user as { id?: string; isAdmin?: boolean }).isAdmin = + token.isAdmin === true; } return session; }, diff --git a/apps/app-portal/src/lib/auth/guards.ts b/apps/app-portal/src/lib/auth/guards.ts index 087b4384..7102573c 100644 --- a/apps/app-portal/src/lib/auth/guards.ts +++ b/apps/app-portal/src/lib/auth/guards.ts @@ -11,9 +11,8 @@ export async function requireUser() { export async function requireAdmin() { const user = await requireUser(); - // if (!(user as { isAdmin?: boolean }).isAdmin) { - // throw new Error("Forbidden"); - // } - //TODO: finish admin role + if (!(user as { isAdmin?: boolean }).isAdmin) { + throw new Error("Forbidden"); + } return user; } diff --git a/apps/app-portal/src/lib/auth/roles.ts b/apps/app-portal/src/lib/auth/roles.ts new file mode 100644 index 00000000..578e2ae7 --- /dev/null +++ b/apps/app-portal/src/lib/auth/roles.ts @@ -0,0 +1,7 @@ +//admin role check, shared by server (jwt callback, guards) and client (sign-in form) + +export const ADMIN_EMAIL_DOMAIN = "@hackbeanpot.com"; + +export function isAdminEmail(email?: string | null): boolean { + return !!email?.trim().toLowerCase().endsWith(ADMIN_EMAIL_DOMAIN); +} From 2fb1bdc6ea8cf9b0ad98a5864abb8c2027b5aaad Mon Sep 17 00:00:00 2001 From: adityapat24 Date: Wed, 15 Jul 2026 13:59:39 -0400 Subject: [PATCH 11/12] package change --- apps/app-portal/jest.config.ts | 2 +- apps/app-portal/package.json | 2 +- .../src/app/(applicant)/rsvp/page.tsx | 4 +- .../app-portal/src/app/api/v1/status/route.ts | 2 +- .../src/app/api/v1/uploads/sign/route.ts | 10 +- .../src/lib/auth/email-transport.ts | 43 +- apps/app-portal/src/lib/db.ts | 2 +- .../src/lib/status/fetchPortalStatus.ts | 2 +- .../app-portal/src/lib/status/machine.test.ts | 16 +- apps/app-portal/src/lib/status/machine.ts | 8 +- apps/app-portal/src/lib/status/service.ts | 10 +- apps/app-portal/src/lib/status/types.ts | 2 +- apps/app-portal/src/lib/uploads/gcs.ts | 13 +- apps/app-portal/src/lib/uploads/service.ts | 53 +- apps/app-portal/src/lib/uploads/validation.ts | 20 +- apps/app-portal/tsconfig.json | 5 +- package-lock.json | 953 ++++++++++++++++-- yarn.lock | 757 +++++++++----- 18 files changed, 1481 insertions(+), 423 deletions(-) diff --git a/apps/app-portal/jest.config.ts b/apps/app-portal/jest.config.ts index 75254737..8ffc9a53 100644 --- a/apps/app-portal/jest.config.ts +++ b/apps/app-portal/jest.config.ts @@ -8,4 +8,4 @@ const config: Config = { }, }; -export default config; \ No newline at end of file +export default config; diff --git a/apps/app-portal/package.json b/apps/app-portal/package.json index 033b42e4..982d6f93 100644 --- a/apps/app-portal/package.json +++ b/apps/app-portal/package.json @@ -30,7 +30,7 @@ "mongodb": "^5.9.2", "next": "^14.2.3", "next-auth": "^4.24.14", - "nodemailer": "^9.0.1", + "nodemailer": "^7.0.7", "react": "^18.2.0", "react-day-picker": "^10.0.1", "react-dom": "^18.2.0", diff --git a/apps/app-portal/src/app/(applicant)/rsvp/page.tsx b/apps/app-portal/src/app/(applicant)/rsvp/page.tsx index 4bb55331..c9c54c79 100644 --- a/apps/app-portal/src/app/(applicant)/rsvp/page.tsx +++ b/apps/app-portal/src/app/(applicant)/rsvp/page.tsx @@ -3,6 +3,8 @@ import { redirect } from "next/navigation"; import { fetchPortalStatus } from "../../../lib/status/fetchPortalStatus"; import RsvpExperience from "../../../components/dashboard/RsvpExperience"; +export const dynamic = "force-dynamic"; + export default async function RsvpPage(): Promise { const { branch, status, decisionDates } = await fetchPortalStatus(); const confirmBy = new Date(decisionDates.confirmBy); @@ -14,7 +16,7 @@ export default async function RsvpPage(): Promise { return ( ); diff --git a/apps/app-portal/src/app/api/v1/status/route.ts b/apps/app-portal/src/app/api/v1/status/route.ts index 3e38c0de..0e306333 100644 --- a/apps/app-portal/src/app/api/v1/status/route.ts +++ b/apps/app-portal/src/app/api/v1/status/route.ts @@ -32,4 +32,4 @@ export async function GET(req: NextRequest) { export async function POST() { return NextResponse.json({ error: "error 501" }, { status: 501 }); -} \ No newline at end of file +} diff --git a/apps/app-portal/src/app/api/v1/uploads/sign/route.ts b/apps/app-portal/src/app/api/v1/uploads/sign/route.ts index abf1357b..a066a92f 100644 --- a/apps/app-portal/src/app/api/v1/uploads/sign/route.ts +++ b/apps/app-portal/src/app/api/v1/uploads/sign/route.ts @@ -1,6 +1,9 @@ // POST --> returns signed upload URL for GCS; stub returns 501 -import { createSignedUploadUrl, InvalidUploadError } from "@/lib/uploads/service"; +import { + createSignedUploadUrl, + InvalidUploadError, +} from "@/lib/uploads/service"; import { NextResponse } from "next/server"; export async function POST(request: Request) { @@ -12,7 +15,10 @@ export async function POST(request: Request) { try { const { uploadId, uploadUrl, expiresAt } = await createSignedUploadUrl({ - userId, filename, mime, size, + userId, + filename, + mime, + size, }); return NextResponse.json({ uploadId, uploadUrl: uploadUrl, expiresAt }); } catch (err) { diff --git a/apps/app-portal/src/lib/auth/email-transport.ts b/apps/app-portal/src/lib/auth/email-transport.ts index a67cb2ea..7fd36188 100644 --- a/apps/app-portal/src/lib/auth/email-transport.ts +++ b/apps/app-portal/src/lib/auth/email-transport.ts @@ -1,28 +1,28 @@ import EmailProvider from "next-auth/providers/email"; import type { SendVerificationRequestParams } from "next-auth/providers/email"; -import { createTransport } from "nodemailer" -import {Theme} from "next-auth"; +import { createTransport } from "nodemailer"; +import { Theme } from "next-auth"; import { readFileSync } from "fs"; import { join } from "path"; const TEMPLATE_PATH = join(process.cwd(), "src/lib/auth/email-template.html"); async function customRequest(params: SendVerificationRequestParams) { - const { identifier, url, provider, theme } = params - const { host } = new URL(url) + const { identifier, url, provider, theme } = params; + const { host } = new URL(url); - const transport = createTransport(provider.server) + const transport = createTransport(provider.server); const result = await transport.sendMail({ to: identifier, from: provider.from, subject: `Verify your identity for HackBeanpot`, text: text({ url, host }), html: html({ url, host, theme }), - }) - const failed = result.rejected.concat(result.pending).filter(Boolean) + }); + const failed = result.rejected.concat(result.pending).filter(Boolean); if (failed.length) { - throw new Error(`Email(s) (${failed.join(", ")}) could not be sent`) + throw new Error(`Email(s) (${failed.join(", ")}) could not be sent`); } } @@ -34,10 +34,10 @@ async function customRequest(params: SendVerificationRequestParams) { * * @note We don't add the email address to avoid needing to escape it, if you do, remember to sanitize it! */ -function html(params: { url: string, host: string, theme: Theme }) { - const { url, theme } = params +function html(params: { url: string; host: string; theme: Theme }) { + const { url, theme } = params; - const brandColor = theme.brandColor || "#346df1" + const brandColor = theme.brandColor || "#346df1"; const color = { background: "#f9f9f9", text: "#444", @@ -45,12 +45,13 @@ function html(params: { url: string, host: string, theme: Theme }) { buttonBackground: brandColor, buttonBorder: brandColor, buttonText: theme.buttonText || "#fff", - } + }; // Logo is served from /public; use an absolute URL so email clients can load it. // Derive the origin (NEXTAUTH_URL may carry an /auth path we must strip). - const origin = new URL(process.env.NEXTAUTH_URL ?? "http://localhost:3000").origin - const logoUrl = `${origin}/email_logo.png` + const origin = new URL(process.env.NEXTAUTH_URL ?? "http://localhost:3000") + .origin; + const logoUrl = `${origin}/email_logo.png`; const replacements: Record = { url, @@ -61,18 +62,18 @@ function html(params: { url: string, host: string, theme: Theme }) { buttonBackground: color.buttonBackground, buttonBorder: color.buttonBorder, buttonText: color.buttonText, - } + }; - let template = readFileSync(TEMPLATE_PATH, "utf8") + let template = readFileSync(TEMPLATE_PATH, "utf8"); for (const [key, value] of Object.entries(replacements)) { - template = template.replaceAll(`{{${key}}}`, value) + template = template.replaceAll(`{{${key}}}`, value); } - return template + return template; } /** Email Text body (fallback for email clients that don't render HTML, e.g. feature phones) */ -function text({ url, host }: { url: string, host: string }) { - return `Sign in to ${host}\n${url}\n\n` +function text({ url, host }: { url: string; host: string }) { + return `Sign in to ${host}\n${url}\n\n`; } const config = EmailProvider({ @@ -86,7 +87,7 @@ const config = EmailProvider({ }, from: process.env.EMAIL_FROM, sendVerificationRequest(params) { - return customRequest(params) + return customRequest(params); }, }); diff --git a/apps/app-portal/src/lib/db.ts b/apps/app-portal/src/lib/db.ts index 125e3376..b1443814 100644 --- a/apps/app-portal/src/lib/db.ts +++ b/apps/app-portal/src/lib/db.ts @@ -53,4 +53,4 @@ export function resolveCollectionName(baseName: string): string { } // need client promise for the NextAuth MongoDB adapter -export const mongoClientPromise = clientPromise; +export const mongoClientPromise = getClientPromise(uri); diff --git a/apps/app-portal/src/lib/status/fetchPortalStatus.ts b/apps/app-portal/src/lib/status/fetchPortalStatus.ts index 83421ae7..9570a510 100644 --- a/apps/app-portal/src/lib/status/fetchPortalStatus.ts +++ b/apps/app-portal/src/lib/status/fetchPortalStatus.ts @@ -52,4 +52,4 @@ export async function fetchPortalStatus(): Promise { }, }; } -} \ No newline at end of file +} diff --git a/apps/app-portal/src/lib/status/machine.test.ts b/apps/app-portal/src/lib/status/machine.test.ts index 36df9001..47a9acdd 100644 --- a/apps/app-portal/src/lib/status/machine.test.ts +++ b/apps/app-portal/src/lib/status/machine.test.ts @@ -4,12 +4,14 @@ import type { ApplicantStatus, MachineInput } from "./types"; const PAST = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000); const FUTURE = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000); -function makeInput(overrides: { - user?: Partial; - dates?: { registrationOpen: Date; confirmBy: Date }; - showDecision?: boolean; - now?: Date; -} = {}): MachineInput { +function makeInput( + overrides: { + user?: Partial; + dates?: { registrationOpen: Date; confirmBy: Date }; + showDecision?: boolean; + now?: Date; + } = {}, +): MachineInput { return { user: { userId: "test-user", @@ -83,4 +85,4 @@ describe("returnDashboardBranch", () => { }); expect(returnDashboardBranch(input)).toBe("declined"); }); -}); \ No newline at end of file +}); diff --git a/apps/app-portal/src/lib/status/machine.ts b/apps/app-portal/src/lib/status/machine.ts index 28e54e0c..67426272 100644 --- a/apps/app-portal/src/lib/status/machine.ts +++ b/apps/app-portal/src/lib/status/machine.ts @@ -11,7 +11,11 @@ export function returnDashboardBranch(input: MachineInput): DashboardBranch { return "in-progress"; } - if (!showDecision || !user.decisionStatus || user.decisionStatus === "pending") { + if ( + !showDecision || + !user.decisionStatus || + user.decisionStatus === "pending" + ) { return "submitted"; } @@ -25,4 +29,4 @@ export function returnDashboardBranch(input: MachineInput): DashboardBranch { default: return "submitted"; } -} \ No newline at end of file +} diff --git a/apps/app-portal/src/lib/status/service.ts b/apps/app-portal/src/lib/status/service.ts index 3cad24d5..f14e1e01 100644 --- a/apps/app-portal/src/lib/status/service.ts +++ b/apps/app-portal/src/lib/status/service.ts @@ -8,7 +8,9 @@ import type { RsvpStatus, } from "./types"; -export async function getApplicantStatus(userId: string): Promise { +export async function getApplicantStatus( + userId: string, +): Promise { const db = await getDb(); const doc = await db.collection("applicant_data").findOne({ userId }); @@ -29,7 +31,9 @@ export async function getApplicantStatus(userId: string): Promise { +export async function getPortalStatus( + userId: string, +): Promise { const user = await getApplicantStatus(userId); // TODO: replace with getSingleton() calls once Ticket 5 lands real singleton service @@ -64,4 +68,4 @@ export async function saveRsvp( void payload; mockApplicantStatus.rsvpStatus = "confirmed"; return "confirmed"; -} \ No newline at end of file +} diff --git a/apps/app-portal/src/lib/status/types.ts b/apps/app-portal/src/lib/status/types.ts index 185fd0ba..32c13a8c 100644 --- a/apps/app-portal/src/lib/status/types.ts +++ b/apps/app-portal/src/lib/status/types.ts @@ -55,4 +55,4 @@ export type PortalStatusResponse = { branch: DashboardBranch; status: ApplicantStatus; decisionDates: SerializedDecisionDates; -}; \ No newline at end of file +}; diff --git a/apps/app-portal/src/lib/uploads/gcs.ts b/apps/app-portal/src/lib/uploads/gcs.ts index 393eeaa2..5c6537c8 100644 --- a/apps/app-portal/src/lib/uploads/gcs.ts +++ b/apps/app-portal/src/lib/uploads/gcs.ts @@ -7,11 +7,10 @@ class GCSClient { private storage: Storage; private constructor() { - const credentials = { client_email: process.env.GOOGLE_CLOUD_EMAIL, private_key: process.env.GOOGLE_CLOUD_PRIVATE_KEY?.replace(/\\n/g, "\n"), - } + }; if (!process.env.GOOGLE_CLOUD_PROJECT_ID) { throw new Error("Missing GCS env vars"); @@ -19,7 +18,7 @@ class GCSClient { this.storage = new Storage({ projectId: process.env.GOOGLE_CLOUD_PROJECT_ID, - credentials + credentials, }); } @@ -31,13 +30,13 @@ class GCSClient { } public getBucket(): Bucket { - if (process.env.NODE_ENV === 'production') { + if (process.env.NODE_ENV === "production") { return this.storage.bucket( - process.env.GOOGLE_CLOUD_STORAGE_RESUME_BUCKET! - ) + process.env.GOOGLE_CLOUD_STORAGE_RESUME_BUCKET!, + ); } return this.storage.bucket( - process.env.GOOGLE_CLOUD_STORAGE_RESUME_BUCKET_TEST! + process.env.GOOGLE_CLOUD_STORAGE_RESUME_BUCKET_TEST!, ); } } diff --git a/apps/app-portal/src/lib/uploads/service.ts b/apps/app-portal/src/lib/uploads/service.ts index d382539a..439bed21 100644 --- a/apps/app-portal/src/lib/uploads/service.ts +++ b/apps/app-portal/src/lib/uploads/service.ts @@ -3,30 +3,39 @@ import { sanitizeFileName, validateUploadRequest } from "./validation"; import { gcsBucket } from "./gcs"; - export class InvalidUploadError extends Error {} -export async function createSignedUploadUrl({ userId, filename, mime, size } : { userId: string; filename: string; mime: string; size: number }): Promise<{ uploadUrl: string, uploadId: string, expiresAt: Date }> { - const result = validateUploadRequest({mime, size, filename}); - if (!result.ok) { - throw new InvalidUploadError(result.error); - } - - const uploadId = crypto.randomUUID(); - const cleanFileName = sanitizeFileName(filename); - - const path = `uploads/${userId}/${uploadId}/${cleanFileName}`; - - const expireDate = Date.now() + 15 * 60 * 1000; - - const [uploadUrl] = await gcsBucket().file(path).getSignedUrl({ - version: "v4", - action: "write", - expires: expireDate, - contentType: mime, - }) - - return { uploadUrl, uploadId, expiresAt: new Date(expireDate)} +export async function createSignedUploadUrl({ + userId, + filename, + mime, + size, +}: { + userId: string; + filename: string; + mime: string; + size: number; +}): Promise<{ uploadUrl: string; uploadId: string; expiresAt: Date }> { + const result = validateUploadRequest({ mime, size, filename }); + if (!result.ok) { + throw new InvalidUploadError(result.error); + } + + const uploadId = crypto.randomUUID(); + const cleanFileName = sanitizeFileName(filename); + + const path = `uploads/${userId}/${uploadId}/${cleanFileName}`; + + const expireDate = Date.now() + 15 * 60 * 1000; + + const [uploadUrl] = await gcsBucket().file(path).getSignedUrl({ + version: "v4", + action: "write", + expires: expireDate, + contentType: mime, + }); + + return { uploadUrl, uploadId, expiresAt: new Date(expireDate) }; } // createSignedDownloadUrl() diff --git a/apps/app-portal/src/lib/uploads/validation.ts b/apps/app-portal/src/lib/uploads/validation.ts index ccee8361..d1eebce9 100644 --- a/apps/app-portal/src/lib/uploads/validation.ts +++ b/apps/app-portal/src/lib/uploads/validation.ts @@ -15,18 +15,26 @@ export function sanitizeFileName(filename: string): string { return cleanName || "unnamed"; } -export function validateUploadRequest({ mime, size, filename} : {mime: string; size: number; filename: string}) : {ok: true} | {ok: false, error: string} { +export function validateUploadRequest({ + mime, + size, + filename, +}: { + mime: string; + size: number; + filename: string; +}): { ok: true } | { ok: false; error: string } { if (!(ALLOWED_MIME_TYPES as readonly string[]).includes(mime)) { - return {ok: false, error: "Incorrect mime type"}; + return { ok: false, error: "Incorrect mime type" }; } if (size <= 0) { - return {ok: false, error: "File is empty"}; + return { ok: false, error: "File is empty" }; } if (size > MAX_FILE_SIZE_BYTES) { - return {ok: false, error: "Size of file is too large (over 5 MB)"}; + return { ok: false, error: "Size of file is too large (over 5 MB)" }; } if (!filename || filename.trim().length === 0) { - return {ok: false, error: "Filename is required"} + return { ok: false, error: "Filename is required" }; } - return {ok: true}; + return { ok: true }; } diff --git a/apps/app-portal/tsconfig.json b/apps/app-portal/tsconfig.json index c8c03b48..cf4591cf 100644 --- a/apps/app-portal/tsconfig.json +++ b/apps/app-portal/tsconfig.json @@ -5,8 +5,7 @@ "paths": { "@/*": ["./src/*"], "@util/*": ["../../packages/util/src/*"] - }, - "types": ["jest"] + } }, "include": [ "next-env.d.ts", @@ -15,5 +14,5 @@ ".next/types/**/*.ts", "../../packages/ui/src/Placeholder.tsx" ], - "exclude": ["node_modules"] + "exclude": ["node_modules", "jest.config.ts", "**/*.test.ts", "**/*.test.tsx"] } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 0d9ea589..c60ea787 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,8 +36,9 @@ "apps/app-portal": { "version": "1.0.0", "dependencies": { - "@google-cloud/storage": "^7.19.0", + "@google-cloud/storage": "^7.21.0", "@hookform/resolvers": "^5.2.2", + "@next-auth/mongodb-adapter": "^1.1.3", "@radix-ui/react-checkbox": "^1.3.3", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-label": "^2.1.8", @@ -50,13 +51,17 @@ "clsx": "^2.1.1", "date-fns": "^4.4.0", "lucide-react": "^1.14.0", - "mongodb": "^7.2.0", + "mongodb": "^5.9.2", "next": "^14.2.3", + "next-auth": "^4.24.14", + "nodemailer": "^7.0.7", "react": "^18.2.0", "react-day-picker": "^10.0.1", "react-dom": "^18.2.0", + "react-dropzone": "^15.0.0", "react-hook-form": "^7.75.0", "recharts": "3.8.0", + "server-only": "^0.0.1", "sonner": "^2.0.7", "tailwind-merge": "^3.5.0", "zod": "^4.4.3" @@ -69,12 +74,14 @@ "@repo/tailwind-config": "*", "@repo/typescript-config": "*", "@types/node": "^20.11.24", + "@types/nodemailer": "^8.0.1", "@types/react": "^18.2.61", "@types/react-dom": "^18.2.19", "autoprefixer": "^10.4.18", "eslint-config-next": "15.0.3", "postcss": "^8.4.35", "tailwindcss": "^3.4.1", + "tsx": "^4.19.2", "typescript": "5.5.4" } }, @@ -188,7 +195,6 @@ "integrity": "sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", @@ -409,6 +415,15 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", @@ -490,7 +505,6 @@ "resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz", "integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==", "license": "MIT", - "peer": true, "dependencies": { "@dnd-kit/accessibility": "^3.1.1", "@dnd-kit/utilities": "^3.2.2", @@ -527,6 +541,448 @@ "react": ">=16.8.0" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.9.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", @@ -759,9 +1215,9 @@ } }, "node_modules/@google-cloud/storage": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-7.19.0.tgz", - "integrity": "sha512-n2FjE7NAOYyshogdc7KQOl/VZb4sneqPjWouSyia9CMDdMhRX5+RIbqalNmC7LOLzuLAN89VlF2HvG8na9G+zQ==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-7.21.0.tgz", + "integrity": "sha512-l+IFTkd+6Y5LoAuXyYCKNAKtw/Ci+rAMqgdTB1jv4iZiLhw0rtq+0qjIRbBizXkNzEFmXiXUW0H7sZQQvk1ffA==", "license": "Apache-2.0", "dependencies": { "@google-cloud/paginator": "^5.0.0", @@ -777,23 +1233,12 @@ "mime": "^3.0.0", "p-limit": "^3.0.1", "retry-request": "^7.0.0", - "teeny-request": "^9.0.0", - "uuid": "^8.0.0" + "teeny-request": "^9.0.0" }, "engines": { "node": ">=14" } }, - "node_modules/@google-cloud/storage/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/@hookform/resolvers": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-5.2.2.tgz", @@ -837,6 +1282,7 @@ "deprecated": "Use @eslint/config-array instead", "dev": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", @@ -866,7 +1312,8 @@ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "deprecated": "Use @eslint/object-schema instead", "dev": true, - "license": "BSD-3-Clause" + "license": "BSD-3-Clause", + "peer": true }, "node_modules/@humanwhocodes/retry": { "version": "0.4.3", @@ -1021,10 +1468,21 @@ "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.4.11.tgz", "integrity": "sha512-o9rAHc0IpIjuPSxRutWpE1F62x7n+4mVS4rCNHkzhIUMQcc18bb6xEq5wd2NdN0WjepIyXIppRshYI2kQDOZVA==", "license": "MIT", + "optional": true, "dependencies": { "sparse-bitfield": "^3.0.3" } }, + "node_modules/@next-auth/mongodb-adapter": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@next-auth/mongodb-adapter/-/mongodb-adapter-1.1.3.tgz", + "integrity": "sha512-nH/may8hntYBlcuxepSsR2b95w6SRnP+c/FFt3KKjdTScNjhrN0zZdlT90nisjG/3gK+MvzMbz/F4Rwpgr9RMA==", + "license": "ISC", + "peerDependencies": { + "mongodb": "^5 || ^4", + "next-auth": "^4" + } + }, "node_modules/@next/env": { "version": "14.2.35", "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.35.tgz", @@ -1255,6 +1713,15 @@ "node": ">=12.4.0" } }, + "node_modules/@panva/hkdf": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.2.1.tgz", + "integrity": "sha512-6oclG6Y3PiDFcoyk8srjLfVKyMfVCKJ27JwNPViuXziFpmdz+MZnZN/aKY0JGXgYuO/VghU0jcOAZgWXZ1Dmrw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -2306,6 +2773,16 @@ "undici-types": "~6.19.2" } }, + "node_modules/@types/nodemailer": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-8.0.1.tgz", + "integrity": "sha512-PxpaInm8V1JQDd4j0ds5HfvWQk8JupS1C0Picb96QJsrrRDjBH+DlK7L4ZdNSqNULhiZRQHc40nLVShaGxXAMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/normalize-package-data": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", @@ -2326,7 +2803,6 @@ "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -2338,7 +2814,6 @@ "integrity": "sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==", "devOptional": true, "license": "MIT", - "peer": true, "peerDependencies": { "@types/react": "^18.0.0" } @@ -2381,11 +2856,12 @@ "license": "MIT" }, "node_modules/@types/whatwg-url": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-13.0.0.tgz", - "integrity": "sha512-N8WXpbE6Wgri7KUSvrmQcqrMllKZ9uxkYWMt+mCSGwNc0Hsw9VQTW7ApqI4XNrx6/SaM2QQJCzMPDEXE058s+Q==", + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", + "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", "license": "MIT", "dependencies": { + "@types/node": "*", "@types/webidl-conversions": "*" } }, @@ -2395,7 +2871,6 @@ "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "7.18.0", @@ -2458,7 +2933,6 @@ "integrity": "sha512-h2lUByouOXFAlMec2mILeELUbME5SZRN/7R9Cw2RD2lRQQY08MWMM+PmVVKKJNK1aIwqTo9t/0CvOxwPbRIE2Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.23.0", "@typescript-eslint/types": "8.23.0", @@ -2768,7 +3242,8 @@ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", "dev": true, - "license": "ISC" + "license": "ISC", + "peer": true }, "node_modules/@vercel/style-guide": { "version": "6.0.0", @@ -2875,7 +3350,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3214,6 +3688,15 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT" }, + "node_modules/attr-accept": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.5.tgz", + "integrity": "sha512-0bDNnY/u6pPwHDMoF0FieU354oBi0a8rD9FcsLwzcGWbc8KS8KPIi7y+s13OlVY+gMWc/9xEMUgNE6Qm8ZllYQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/autoprefixer": { "version": "10.4.20", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", @@ -3381,7 +3864,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", @@ -3396,12 +3878,12 @@ } }, "node_modules/bson": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-7.2.0.tgz", - "integrity": "sha512-YCEo7KjMlbNlyHhz7zAZNDpIpQbd+wOEHJYezv0nMYTn4x31eIUM2yomNNubclAt63dObUzKHWsBLJ9QcZNSnQ==", + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/bson/-/bson-5.5.1.tgz", + "integrity": "sha512-ix0EwukN2EpC0SRWIj/7B5+A6uQMQy6KMREI9qQqvgpkV2frH63T0UDVd1SYedL6dNCmDBYB3QtXi4ISk9YT+g==", "license": "Apache-2.0", "engines": { - "node": ">=20.19.0" + "node": ">=14.20.1" } }, "node_modules/buffer-equal-constant-time": { @@ -3677,6 +4159,15 @@ "dev": true, "license": "MIT" }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/core-js-compat": { "version": "3.40.0", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.40.0.tgz", @@ -4338,6 +4829,48 @@ "benchmarks" ] }, + "node_modules/esbuild": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -4860,7 +5393,6 @@ "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.8", @@ -5467,6 +5999,7 @@ "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -5491,6 +6024,7 @@ "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } @@ -5501,6 +6035,7 @@ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "esutils": "^2.0.2" }, @@ -5514,6 +6049,7 @@ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10" }, @@ -5527,6 +6063,7 @@ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -5544,6 +6081,7 @@ "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", @@ -5562,6 +6100,7 @@ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "license": "ISC", + "peer": true, "dependencies": { "is-glob": "^4.0.3" }, @@ -5759,6 +6298,7 @@ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "flat-cache": "^3.0.4" }, @@ -5766,6 +6306,18 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/file-selector": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/file-selector/-/file-selector-2.1.2.tgz", + "integrity": "sha512-QgXo+mXTe8ljeqUFaX3QVHc5osSItJ/Km+xpocx0aSqWGMSCf6qYs/VnzZgS864Pjn5iceMRFigeAV7AfTlaig==", + "license": "MIT", + "dependencies": { + "tslib": "^2.7.0" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -5802,6 +6354,7 @@ "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.3", @@ -5887,7 +6440,8 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true, - "license": "ISC" + "license": "ISC", + "peer": true }, "node_modules/fsevents": { "version": "2.3.3", @@ -6519,6 +7073,7 @@ "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, "license": "ISC", + "peer": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -6554,6 +7109,15 @@ "node": ">=12" } }, + "node_modules/ip-address": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", + "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, "node_modules/is-array-buffer": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", @@ -6849,6 +7413,7 @@ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=8" } @@ -7080,7 +7645,6 @@ "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", "dev": true, "license": "MIT", - "peer": true, "bin": { "jiti": "bin/jiti.js" } @@ -7092,6 +7656,15 @@ "dev": true, "license": "MIT" }, + "node_modules/jose": { + "version": "4.15.9", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz", + "integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -7353,7 +7926,8 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/merge2": { "version": "1.4.1", @@ -7456,26 +8030,27 @@ } }, "node_modules/mongodb": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-7.2.0.tgz", - "integrity": "sha512-F/2+BMZtLVhY30ioZp0dAmZ+IRZMBqI+nrv6t5+9/1AIwCa8sMRC3jBf81lpxMhnZgqq8CoUD503Z1oZWq1/sw==", + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.9.2.tgz", + "integrity": "sha512-H60HecKO4Bc+7dhOv4sJlgvenK4fQNqqUIlXxZYQNbfEWSALGAwGoyJd/0Qwk4TttFXUOHJ2ZJQe/52ScaUwtQ==", "license": "Apache-2.0", "dependencies": { - "@mongodb-js/saslprep": "^1.3.0", - "bson": "^7.2.0", - "mongodb-connection-string-url": "^7.0.0" + "bson": "^5.5.0", + "mongodb-connection-string-url": "^2.6.0", + "socks": "^2.7.1" }, "engines": { - "node": ">=20.19.0" + "node": ">=14.20.1" + }, + "optionalDependencies": { + "@mongodb-js/saslprep": "^1.1.0" }, "peerDependencies": { - "@aws-sdk/credential-providers": "^3.806.0", - "@mongodb-js/zstd": "^7.0.0", - "gcp-metadata": "^7.0.1", - "kerberos": "^7.0.0", - "mongodb-client-encryption": ">=7.0.0 <7.1.0", - "snappy": "^7.3.2", - "socks": "^2.8.6" + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.0.0", + "kerberos": "^1.0.0 || ^2.0.0", + "mongodb-client-encryption": ">=2.3.0 <3", + "snappy": "^7.2.2" }, "peerDependenciesMeta": { "@aws-sdk/credential-providers": { @@ -7484,9 +8059,6 @@ "@mongodb-js/zstd": { "optional": true }, - "gcp-metadata": { - "optional": true - }, "kerberos": { "optional": true }, @@ -7495,23 +8067,17 @@ }, "snappy": { "optional": true - }, - "socks": { - "optional": true } } }, "node_modules/mongodb-connection-string-url": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-7.0.1.tgz", - "integrity": "sha512-h0AZ9A7IDVwwHyMxmdMXKy+9oNlF0zFoahHiX3vQ8e3KFcSP3VmsmfvtRSuLPxmyv2vjIDxqty8smTgie/SNRQ==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", + "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", "license": "Apache-2.0", "dependencies": { - "@types/whatwg-url": "^13.0.0", - "whatwg-url": "^14.1.0" - }, - "engines": { - "node": ">=20.19.0" + "@types/whatwg-url": "^8.2.1", + "whatwg-url": "^11.0.0" } }, "node_modules/ms": { @@ -7607,6 +8173,48 @@ } } }, + "node_modules/next-auth": { + "version": "4.24.14", + "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-4.24.14.tgz", + "integrity": "sha512-YRz6xFDXKUwiXSMMChbrBEWyFktZ1qZXEgeSHQQ3nsy08B4c/xLk6REeutRsIFwkjY/1+ShHnu07DN3JeJguig==", + "license": "ISC", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@panva/hkdf": "^1.0.2", + "cookie": "^0.7.0", + "jose": "^4.15.5", + "oauth": "^0.9.15", + "openid-client": "^5.4.0", + "preact": "^10.6.3", + "preact-render-to-string": "^5.1.19", + "uuid": "^8.3.2" + }, + "peerDependencies": { + "@auth/core": "0.34.3", + "next": "^12.2.5 || ^13 || ^14 || ^15 || ^16", + "nodemailer": "^7.0.7", + "react": "^17.0.2 || ^18 || ^19", + "react-dom": "^17.0.2 || ^18 || ^19" + }, + "peerDependenciesMeta": { + "@auth/core": { + "optional": true + }, + "nodemailer": { + "optional": true + } + } + }, + "node_modules/next-auth/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/next/node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", @@ -7684,6 +8292,15 @@ "dev": true, "license": "MIT" }, + "node_modules/nodemailer": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.13.tgz", + "integrity": "sha512-PNDFSJdP+KFgdsG3ZzMXCgquO7I6McjY2vlqILjtJd0hy8wEvtugS9xKRF2NWlPNGxvLCXlTNIae4serI7dinw==", + "license": "MIT-0", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -7727,11 +8344,16 @@ "node": ">=0.10.0" } }, + "node_modules/oauth": { + "version": "0.9.15", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", + "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==", + "license": "MIT" + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -7859,6 +8481,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/oidc-token-hash": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.2.0.tgz", + "integrity": "sha512-6gj2m8cJZ+iSW8bm0FXdGF0YhIQbKrfP4yWTNzxc31U6MOjfEmB1rHvlYvxI1B7t7BCi1F2vYTT6YhtQRG4hxw==", + "license": "MIT", + "engines": { + "node": "^10.13.0 || >=12.0.0" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -7868,6 +8499,48 @@ "wrappy": "1" } }, + "node_modules/openid-client": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.7.1.tgz", + "integrity": "sha512-jDBPgSVfTnkIh71Hg9pRvtJc6wTwqjRkN88+gCFtYWrlP4Yx2Dsrow8uPi3qLr/aeymPF3o2+dS+wOpglK04ew==", + "license": "MIT", + "dependencies": { + "jose": "^4.15.9", + "lru-cache": "^6.0.0", + "object-hash": "^2.2.0", + "oidc-token-hash": "^5.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/openid-client/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/openid-client/node_modules/object-hash": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", + "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/openid-client/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -8015,6 +8688,7 @@ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -8142,7 +8816,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", @@ -8273,6 +8946,36 @@ "dev": true, "license": "MIT" }, + "node_modules/preact": { + "version": "10.29.7", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.29.7.tgz", + "integrity": "sha512-DCHYrK/B10yUD3ZjLfhZ3WIE/9Vf9VFUODcRE2dRomTYDpJk6z6L9wecSfhfE6M9ZTHUdyQkoC46arIDhEV84Q==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + }, + "peerDependencies": { + "preact-render-to-string": ">=5" + }, + "peerDependenciesMeta": { + "preact-render-to-string": { + "optional": true + } + } + }, + "node_modules/preact-render-to-string": { + "version": "5.2.6", + "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-5.2.6.tgz", + "integrity": "sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==", + "license": "MIT", + "dependencies": { + "pretty-format": "^3.8.0" + }, + "peerDependencies": { + "preact": ">=10" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -8289,7 +8992,6 @@ "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", "dev": true, "license": "MIT", - "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -8394,11 +9096,16 @@ } } }, + "node_modules/pretty-format": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz", + "integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==", + "license": "MIT" + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", @@ -8441,7 +9148,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -8480,7 +9186,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -8489,12 +9194,28 @@ "react": "^18.3.1" } }, + "node_modules/react-dropzone": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-15.0.0.tgz", + "integrity": "sha512-lGjYV/EoqEjEWPnmiSvH4v5IoIAwQM2W4Z1C0Q/Pw2xD0eVzKPS359BQTUMum+1fa0kH2nrKjuavmTPOGhpLPg==", + "license": "MIT", + "dependencies": { + "attr-accept": "^2.2.4", + "file-selector": "^2.1.0", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">= 10.13" + }, + "peerDependencies": { + "react": ">= 16.8 || 18.0.0" + } + }, "node_modules/react-hook-form": { "version": "7.76.0", "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.76.0.tgz", "integrity": "sha512-eKtLGgFeSgkHqQD8J59AMZ9a4uD1D83iSIzt4YlTGD7liDen5rrjcUO1rVIGd9yC1gofryjtHbv+4ny4hkLWlw==", "license": "MIT", - "peer": true, "engines": { "node": ">=18.0.0" }, @@ -8519,15 +9240,13 @@ "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/react-redux": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.3.0.tgz", "integrity": "sha512-KQopgqFo/p/fgmAs5qz6p5RWaNAzq40WAu7fJIXnQpYxFPbJYtsJPWvGeF2rOBaY/kEuV77AVsX8TsQzKm+A/g==", "license": "MIT", - "peer": true, "dependencies": { "@types/use-sync-external-store": "^0.0.6", "use-sync-external-store": "^1.4.0" @@ -8796,8 +9515,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/redux-thunk": { "version": "3.1.0", @@ -8972,6 +9690,7 @@ "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "license": "ISC", + "peer": true, "dependencies": { "glob": "^7.1.3" }, @@ -8989,6 +9708,7 @@ "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "license": "ISC", + "peer": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -9125,6 +9845,12 @@ "node": ">=10" } }, + "node_modules/server-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz", + "integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==", + "license": "MIT" + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -9296,6 +10022,30 @@ "node": ">=8" } }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.9.tgz", + "integrity": "sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw==", + "license": "MIT", + "dependencies": { + "ip-address": "^10.1.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, "node_modules/sonner": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.7.tgz", @@ -9347,6 +10097,7 @@ "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", "license": "MIT", + "optional": true, "dependencies": { "memory-pager": "^1.0.2" } @@ -9858,7 +10609,6 @@ "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -9984,7 +10734,8 @@ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/thenify": { "version": "3.3.1", @@ -10050,7 +10801,6 @@ "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -10072,15 +10822,15 @@ } }, "node_modules/tr46": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", - "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", "license": "MIT", "dependencies": { - "punycode": "^2.3.1" + "punycode": "^2.1.1" }, "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/ts-api-utils": { @@ -10158,13 +10908,31 @@ "dev": true, "license": "0BSD" }, + "node_modules/tsx": { + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.1.tgz", + "integrity": "sha512-GQHnkIfxyx1wYCOS/wonik5MVRZU9hi1TEZmzGZSCJB1y9YgoZ8H6itNE/u4suE+yLmOzuE4E5S4TZ/ZX2wcWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.28.0" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, "node_modules/turbo": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/turbo/-/turbo-2.4.0.tgz", "integrity": "sha512-ah/yQp2oMif1X0u7fBJ4MLMygnkbKnW5O8SG6pJvloPCpHfFoZctkSVQiJ3VnvNTq71V2JJIdwmOeu1i34OQyg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "turbo": "bin/turbo" }, @@ -10371,7 +11139,6 @@ "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -10805,16 +11572,16 @@ } }, "node_modules/whatwg-url": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", - "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", "license": "MIT", "dependencies": { - "tr46": "^5.1.0", + "tr46": "^3.0.0", "webidl-conversions": "^7.0.0" }, "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/which": { diff --git a/yarn.lock b/yarn.lock index 4a6f5a7b..1db352a8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,11 +2,6 @@ # yarn lockfile v1 -"22@^0.0.0": - version "0.0.0" - resolved "https://registry.npmjs.org/22/-/22-0.0.0.tgz" - integrity sha512-MdBPNDaCFY4fZVpp14n3Mt4isZ2yS1DrIiOig/iMLljr4zDa0g/583xf/lFXNPwhxCfGKYvyWJSrYyS8jNk2mQ== - "@alloc/quick-lru@^5.2.0": version "5.2.0" resolved "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz" @@ -34,7 +29,7 @@ resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.5.tgz" integrity sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg== -"@babel/core@^7.24.0": +"@babel/core@^7.0.0", "@babel/core@^7.11.0", "@babel/core@^7.24.0": version "7.26.7" resolved "https://registry.npmjs.org/@babel/core/-/core-7.26.7.tgz" integrity sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA== @@ -135,7 +130,7 @@ "@babel/runtime@^7.20.13": version "7.29.7" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.29.7.tgz#12022450c45a4da6d8d8287b18a4ff2ddb23f768" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz" integrity sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw== "@babel/template@^7.25.9", "@babel/template@^7.27.2": @@ -180,7 +175,7 @@ dependencies: tslib "^2.0.0" -"@dnd-kit/core@^6.3.1": +"@dnd-kit/core@^6.3.0", "@dnd-kit/core@^6.3.1": version "6.3.1" resolved "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz" integrity sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ== @@ -204,6 +199,11 @@ dependencies: tslib "^2.0.0" +"@esbuild/darwin-x64@0.28.1": + version "0.28.1" + resolved "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz" + integrity sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ== + "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0", "@eslint-community/eslint-utils@^4.8.0": version "4.9.0" resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz" @@ -211,7 +211,7 @@ dependencies: eslint-visitor-keys "^3.4.3" -"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.12.1": +"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.12.1", "@eslint-community/regexpp@^4.6.1": version "4.12.1" resolved "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz" integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== @@ -274,11 +274,16 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@9.39.2", "@eslint/js@^9.14.0": +"@eslint/js@^9.14.0", "@eslint/js@9.39.2": version "9.39.2" resolved "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz" integrity sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA== +"@eslint/js@8.57.1": + version "8.57.1" + resolved "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz" + integrity sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q== + "@eslint/object-schema@^2.1.7": version "2.1.7" resolved "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz" @@ -339,7 +344,7 @@ "@google-cloud/storage@^7.21.0": version "7.21.0" - resolved "https://registry.yarnpkg.com/@google-cloud/storage/-/storage-7.21.0.tgz#46b89afbdc3014e18b60afdfba5d9212a23e7b58" + resolved "https://registry.npmjs.org/@google-cloud/storage/-/storage-7.21.0.tgz" integrity sha512-l+IFTkd+6Y5LoAuXyYCKNAKtw/Ci+rAMqgdTB1jv4iZiLhw0rtq+0qjIRbBizXkNzEFmXiXUW0H7sZQQvk1ffA== dependencies: "@google-cloud/paginator" "^5.0.0" @@ -377,11 +382,25 @@ "@humanfs/core" "^0.19.1" "@humanwhocodes/retry" "^0.4.0" +"@humanwhocodes/config-array@^0.13.0": + version "0.13.0" + resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz" + integrity sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw== + dependencies: + "@humanwhocodes/object-schema" "^2.0.3" + debug "^4.3.1" + minimatch "^3.0.5" + "@humanwhocodes/module-importer@^1.0.1": version "1.0.1" resolved "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== +"@humanwhocodes/object-schema@^2.0.3": + version "2.0.3" + resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz" + integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== + "@humanwhocodes/retry@^0.4.0", "@humanwhocodes/retry@^0.4.2": version "0.4.3" resolved "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz" @@ -447,15 +466,15 @@ integrity sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug== "@mongodb-js/saslprep@^1.1.0": - version "1.4.12" - resolved "https://registry.yarnpkg.com/@mongodb-js/saslprep/-/saslprep-1.4.12.tgz#919ed57f24bb0a9087963fc6e94ee24c37fe08a9" - integrity sha512-QAfAMwNgnYxZ2C6D1HgeP7Gc4i/uvJRim415PCIL9ptRxWMNbWeLBYb2/9R4pGKny/s1FVu2JA2cxCUBUOggrA== + version "1.4.11" + resolved "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.4.11.tgz" + integrity sha512-o9rAHc0IpIjuPSxRutWpE1F62x7n+4mVS4rCNHkzhIUMQcc18bb6xEq5wd2NdN0WjepIyXIppRshYI2kQDOZVA== dependencies: sparse-bitfield "^3.0.3" "@next-auth/mongodb-adapter@^1.1.3": version "1.1.3" - resolved "https://registry.yarnpkg.com/@next-auth/mongodb-adapter/-/mongodb-adapter-1.1.3.tgz#531b75f828338ebd73d8539685641a17804d1d77" + resolved "https://registry.npmjs.org/@next-auth/mongodb-adapter/-/mongodb-adapter-1.1.3.tgz" integrity sha512-nH/may8hntYBlcuxepSsR2b95w6SRnP+c/FFt3KKjdTScNjhrN0zZdlT90nisjG/3gK+MvzMbz/F4Rwpgr9RMA== "@next/env@14.2.35": @@ -463,65 +482,25 @@ resolved "https://registry.npmjs.org/@next/env/-/env-14.2.35.tgz" integrity sha512-DuhvCtj4t9Gwrx80dmz2F4t/zKQ4ktN8WrMwOuVzkJfBilwAwGr6v16M5eI8yCuZ63H9TTuEU09Iu2HqkzFPVQ== -"@next/eslint-plugin-next@15.0.3": - version "15.0.3" - resolved "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.0.3.tgz" - integrity sha512-3Ln/nHq2V+v8uIaxCR6YfYo7ceRgZNXfTd3yW1ukTaFbO+/I8jNakrjYWODvG9BuR2v5kgVtH/C8r0i11quOgw== - dependencies: - fast-glob "3.3.1" - -"@next/eslint-plugin-next@^14.2.3": +"@next/eslint-plugin-next@^14.2.3", "@next/eslint-plugin-next@>=12.3.0 <15.0.0-0": version "14.2.35" resolved "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.35.tgz" integrity sha512-Jw9A3ICz2183qSsqwi7fgq4SBPiNfmOLmTPXKvlnzstUwyvBrtySiY+8RXJweNAs9KThb1+bYhZh9XWcNOr2zQ== dependencies: glob "10.3.10" -"@next/swc-darwin-arm64@14.2.33": - version "14.2.33" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.33.tgz#9e74a4223f1e5e39ca4f9f85709e0d95b869b298" - integrity sha512-HqYnb6pxlsshoSTubdXKu15g3iivcbsMXg4bYpjL2iS/V6aQot+iyF4BUc2qA/J/n55YtvE4PHMKWBKGCF/+wA== +"@next/eslint-plugin-next@15.0.3": + version "15.0.3" + resolved "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.0.3.tgz" + integrity sha512-3Ln/nHq2V+v8uIaxCR6YfYo7ceRgZNXfTd3yW1ukTaFbO+/I8jNakrjYWODvG9BuR2v5kgVtH/C8r0i11quOgw== + dependencies: + fast-glob "3.3.1" "@next/swc-darwin-x64@14.2.33": version "14.2.33" resolved "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.33.tgz" integrity sha512-8HGBeAE5rX3jzKvF593XTTFg3gxeU4f+UWnswa6JPhzaR6+zblO5+fjltJWIZc4aUalqTclvN2QtTC37LxvZAA== -"@next/swc-linux-arm64-gnu@14.2.33": - version "14.2.33" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.33.tgz#837f91a740eb4420c06f34c4677645315479d9be" - integrity sha512-JXMBka6lNNmqbkvcTtaX8Gu5by9547bukHQvPoLe9VRBx1gHwzf5tdt4AaezW85HAB3pikcvyqBToRTDA4DeLw== - -"@next/swc-linux-arm64-musl@14.2.33": - version "14.2.33" - resolved "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.33.tgz" - integrity sha512-Bm+QulsAItD/x6Ih8wGIMfRJy4G73tu1HJsrccPW6AfqdZd0Sfm5Imhgkgq2+kly065rYMnCOxTBvmvFY1BKfg== - -"@next/swc-linux-x64-gnu@14.2.33": - version "14.2.33" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.33.tgz#344438be592b6b28cc540194274561e41f9933e5" - integrity sha512-FnFn+ZBgsVMbGDsTqo8zsnRzydvsGV8vfiWwUo1LD8FTmPTdV+otGSWKc4LJec0oSexFnCYVO4hX8P8qQKaSlg== - -"@next/swc-linux-x64-musl@14.2.33": - version "14.2.33" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.33.tgz#3379fad5e0181000b2a4fac0b80f7ca4ffe795c8" - integrity sha512-345tsIWMzoXaQndUTDv1qypDRiebFxGYx9pYkhwY4hBRaOLt8UGfiWKr9FSSHs25dFIf8ZqIFaPdy5MljdoawA== - -"@next/swc-win32-arm64-msvc@14.2.33": - version "14.2.33" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.33.tgz#bca8f4dde34656aef8e99f1e5696de255c2f00e5" - integrity sha512-nscpt0G6UCTkrT2ppnJnFsYbPDQwmum4GNXYTeoTIdsmMydSKFz9Iny2jpaRupTb+Wl298+Rh82WKzt9LCcqSQ== - -"@next/swc-win32-ia32-msvc@14.2.33": - version "14.2.33" - resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.33.tgz#a69c581483ea51dd3b8907ce33bb101fe07ec1df" - integrity sha512-pc9LpGNKhJ0dXQhZ5QMmYxtARwwmWLpeocFmVG5Z0DzWq5Uf0izcI8tLc+qOpqxO1PWqZ5A7J1blrUIKrIFc7Q== - -"@next/swc-win32-x64-msvc@14.2.33": - version "14.2.33" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.33.tgz#f1a40062530c17c35a86d8c430b3ae465eb7cea1" - integrity sha512-nOjfZMy8B94MdisuzZo9/57xuFVLHJaDj5e/xrduJp9CV2/HrfxTRH2fbyLe+K9QT41WBLUd4iXX3R7jBp0EUg== - "@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": version "5.1.1-v1" resolved "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz" @@ -542,12 +521,12 @@ "@nodelib/fs.stat" "2.0.5" run-parallel "^1.1.9" -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": +"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5": version "2.0.5" resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== -"@nodelib/fs.walk@^1.2.3": +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": version "1.2.8" resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== @@ -562,7 +541,7 @@ "@panva/hkdf@^1.0.2": version "1.2.1" - resolved "https://registry.yarnpkg.com/@panva/hkdf/-/hkdf-1.2.1.tgz#cb0d111ef700136f4580349ff0226bf25c853f23" + resolved "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.2.1.tgz" integrity sha512-6oclG6Y3PiDFcoyk8srjLfVKyMfVCKJ27JwNPViuXziFpmdz+MZnZN/aKY0JGXgYuO/VghU0jcOAZgWXZ1Dmrw== "@pkgjs/parseargs@^0.11.0": @@ -784,6 +763,13 @@ aria-hidden "^1.2.4" react-remove-scroll "^2.6.3" +"@radix-ui/react-slot@^1.2.4", "@radix-ui/react-slot@1.2.4": + version "1.2.4" + resolved "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz" + integrity sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA== + dependencies: + "@radix-ui/react-compose-refs" "1.1.2" + "@radix-ui/react-slot@1.2.3": version "1.2.3" resolved "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz" @@ -791,13 +777,6 @@ dependencies: "@radix-ui/react-compose-refs" "1.1.2" -"@radix-ui/react-slot@1.2.4", "@radix-ui/react-slot@^1.2.4": - version "1.2.4" - resolved "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz" - integrity sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA== - dependencies: - "@radix-ui/react-compose-refs" "1.1.2" - "@radix-ui/react-switch@^1.2.6": version "1.2.6" resolved "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.6.tgz" @@ -886,6 +865,32 @@ redux-thunk "^3.1.0" reselect "^5.1.0" +"@repo/eslint-config@*", "@repo/eslint-config@file:/Users/adityapathak/core/packages/config-eslint": + version "0.0.0" + resolved "file:packages/config-eslint" + +"@repo/tailwind-config@*", "@repo/tailwind-config@file:/Users/adityapathak/core/packages/config-tailwind": + version "0.0.0" + resolved "file:packages/config-tailwind" + +"@repo/typescript-config@*", "@repo/typescript-config@file:/Users/adityapathak/core/packages/config-typescript": + version "0.0.0" + resolved "file:packages/config-typescript" + +"@repo/ui@*", "@repo/ui@file:/Users/adityapathak/core/packages/ui": + version "0.0.0" + resolved "file:packages/ui" + dependencies: + "@repo/util" "*" + clsx "^2.0.0" + react-icons "^5.0.0" + +"@repo/util@*", "@repo/util@file:/Users/adityapathak/core/packages/util": + version "0.0.0" + resolved "file:packages/util" + dependencies: + usehooks-ts "^3.1.0" + "@rtsao/scc@^1.1.0": version "1.1.0" resolved "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz" @@ -1016,7 +1021,7 @@ "@types/nodemailer@^8.0.1": version "8.0.1" - resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-8.0.1.tgz#4ef2b4e62c819225a0b8a6384bf750c0c664d465" + resolved "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-8.0.1.tgz" integrity sha512-PxpaInm8V1JQDd4j0ds5HfvWQk8JupS1C0Picb96QJsrrRDjBH+DlK7L4ZdNSqNULhiZRQHc40nLVShaGxXAMw== dependencies: "@types/node" "*" @@ -1031,12 +1036,12 @@ resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz" integrity sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ== -"@types/react-dom@^18.2.19": +"@types/react-dom@*", "@types/react-dom@^18.2.19": version "18.3.5" resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.5.tgz" integrity sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q== -"@types/react@^18.2.61": +"@types/react@*", "@types/react@^18.0.0", "@types/react@^18.2.25 || ^19", "@types/react@^18.2.61", "@types/react@>=16.8.0": version "18.3.18" resolved "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz" integrity sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ== @@ -1076,13 +1081,28 @@ "@types/whatwg-url@^8.2.1": version "8.2.2" - resolved "https://registry.yarnpkg.com/@types/whatwg-url/-/whatwg-url-8.2.2.tgz#749d5b3873e845897ada99be4448041d4cc39e63" + resolved "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz" integrity sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA== dependencies: "@types/node" "*" "@types/webidl-conversions" "*" -"@typescript-eslint/eslint-plugin@8.23.0", "@typescript-eslint/eslint-plugin@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0": +"@typescript-eslint/eslint-plugin@^5.0.0 || ^6.0.0 || ^7.0.0", "@typescript-eslint/eslint-plugin@^7.1.1": + version "7.18.0" + resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz" + integrity sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw== + dependencies: + "@eslint-community/regexpp" "^4.10.0" + "@typescript-eslint/scope-manager" "7.18.0" + "@typescript-eslint/type-utils" "7.18.0" + "@typescript-eslint/utils" "7.18.0" + "@typescript-eslint/visitor-keys" "7.18.0" + graphemer "^1.4.0" + ignore "^5.3.1" + natural-compare "^1.4.0" + ts-api-utils "^1.3.0" + +"@typescript-eslint/eslint-plugin@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0": version "8.23.0" resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.23.0.tgz" integrity sha512-vBz65tJgRrA1Q5gWlRfvoH+w943dq9K1p1yDBY2pc+a1nbBLZp7fB9+Hk8DaALUbzjqlMfgaqlVPT1REJdkt/w== @@ -1097,22 +1117,22 @@ natural-compare "^1.4.0" ts-api-utils "^2.0.1" -"@typescript-eslint/eslint-plugin@^7.1.1": - version "7.18.0" - resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz" - integrity sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw== +"@typescript-eslint/eslint-plugin@8.23.0": + version "8.23.0" + resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.23.0.tgz" + integrity sha512-vBz65tJgRrA1Q5gWlRfvoH+w943dq9K1p1yDBY2pc+a1nbBLZp7fB9+Hk8DaALUbzjqlMfgaqlVPT1REJdkt/w== dependencies: "@eslint-community/regexpp" "^4.10.0" - "@typescript-eslint/scope-manager" "7.18.0" - "@typescript-eslint/type-utils" "7.18.0" - "@typescript-eslint/utils" "7.18.0" - "@typescript-eslint/visitor-keys" "7.18.0" + "@typescript-eslint/scope-manager" "8.23.0" + "@typescript-eslint/type-utils" "8.23.0" + "@typescript-eslint/utils" "8.23.0" + "@typescript-eslint/visitor-keys" "8.23.0" graphemer "^1.4.0" ignore "^5.3.1" natural-compare "^1.4.0" - ts-api-utils "^1.3.0" + ts-api-utils "^2.0.1" -"@typescript-eslint/parser@8.23.0", "@typescript-eslint/parser@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0": +"@typescript-eslint/parser@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/parser@^8.0.0 || ^8.0.0-alpha.0", "@typescript-eslint/parser@8.23.0": version "8.23.0" resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.23.0.tgz" integrity sha512-h2lUByouOXFAlMec2mILeELUbME5SZRN/7R9Cw2RD2lRQQY08MWMM+PmVVKKJNK1aIwqTo9t/0CvOxwPbRIE2Q== @@ -1123,6 +1143,15 @@ "@typescript-eslint/visitor-keys" "8.23.0" debug "^4.3.4" +"@typescript-eslint/parser@^7.0.0": + version "7.18.0" + dependencies: + "@typescript-eslint/scope-manager" "7.18.0" + "@typescript-eslint/types" "7.18.0" + "@typescript-eslint/typescript-estree" "7.18.0" + "@typescript-eslint/visitor-keys" "7.18.0" + debug "^4.3.4" + "@typescript-eslint/parser@^7.1.1": version "7.18.0" resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz" @@ -1234,7 +1263,35 @@ semver "^7.6.0" ts-api-utils "^2.0.1" -"@typescript-eslint/utils@7.18.0", "@typescript-eslint/utils@^7.1.1": +"@typescript-eslint/utils@^5.10.0": + version "5.62.0" + resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz" + integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@types/json-schema" "^7.0.9" + "@types/semver" "^7.3.12" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/typescript-estree" "5.62.0" + eslint-scope "^5.1.1" + semver "^7.3.7" + +"@typescript-eslint/utils@^5.62.0": + version "5.62.0" + resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz" + integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@types/json-schema" "^7.0.9" + "@types/semver" "^7.3.12" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/typescript-estree" "5.62.0" + eslint-scope "^5.1.1" + semver "^7.3.7" + +"@typescript-eslint/utils@^7.1.1", "@typescript-eslint/utils@7.18.0": version "7.18.0" resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz" integrity sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw== @@ -1254,20 +1311,6 @@ "@typescript-eslint/types" "8.23.0" "@typescript-eslint/typescript-estree" "8.23.0" -"@typescript-eslint/utils@^5.10.0", "@typescript-eslint/utils@^5.62.0": - version "5.62.0" - resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz" - integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== - dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@types/json-schema" "^7.0.9" - "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.62.0" - "@typescript-eslint/types" "5.62.0" - "@typescript-eslint/typescript-estree" "5.62.0" - eslint-scope "^5.1.1" - semver "^7.3.7" - "@typescript-eslint/visitor-keys@5.62.0": version "5.62.0" resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz" @@ -1292,6 +1335,11 @@ "@typescript-eslint/types" "8.23.0" eslint-visitor-keys "^4.2.0" +"@ungap/structured-clone@^1.2.0": + version "1.3.0" + resolved "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz" + integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g== + "@vercel/style-guide@^6.0.0": version "6.0.0" resolved "https://registry.npmjs.org/@vercel/style-guide/-/style-guide-6.0.0.tgz" @@ -1318,6 +1366,11 @@ eslint-plugin-vitest "^0.3.22" prettier-plugin-packagejson "^2.4.12" +"22@^0.0.0": + version "0.0.0" + resolved "https://registry.npmjs.org/22/-/22-0.0.0.tgz" + integrity sha512-MdBPNDaCFY4fZVpp14n3Mt4isZ2yS1DrIiOig/iMLljr4zDa0g/583xf/lFXNPwhxCfGKYvyWJSrYyS8jNk2mQ== + abort-controller@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz" @@ -1330,11 +1383,16 @@ acorn-jsx@^5.3.2: resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.15.0, acorn@^8.9.0: +"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.15.0, acorn@^8.9.0: version "8.15.0" resolved "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz" integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== +agent-base@^7.1.2: + version "7.1.4" + resolved "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz" + integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ== + agent-base@6: version "6.0.2" resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" @@ -1342,11 +1400,6 @@ agent-base@6: dependencies: debug "4" -agent-base@^7.1.2: - version "7.1.4" - resolved "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz" - integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ== - ajv@^6.12.4, ajv@~6.12.6: version "6.12.6" resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" @@ -1392,6 +1445,35 @@ anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" +"app-portal@file:/Users/adityapathak/core/apps/app-portal": + version "1.0.0" + resolved "file:apps/app-portal" + dependencies: + "@google-cloud/storage" "^7.19.0" + "@hookform/resolvers" "^5.2.2" + "@radix-ui/react-checkbox" "^1.3.3" + "@radix-ui/react-dialog" "^1.1.15" + "@radix-ui/react-label" "^2.1.8" + "@radix-ui/react-select" "^2.2.6" + "@radix-ui/react-slot" "^1.2.4" + "@repo/ui" "*" + "@repo/util" "*" + "@tanstack/react-table" "^8.20.5" + class-variance-authority "^0.7.1" + clsx "^2.1.1" + date-fns "^4.4.0" + lucide-react "^1.14.0" + mongodb "^7.2.0" + next "^14.2.3" + react "^18.2.0" + react-day-picker "^10.0.1" + react-dom "^18.2.0" + react-hook-form "^7.75.0" + recharts "3.8.0" + sonner "^2.0.7" + tailwind-merge "^3.5.0" + zod "^4.4.3" + arg@^5.0.2: version "5.0.2" resolved "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz" @@ -1536,7 +1618,7 @@ asynckit@^0.4.0: attr-accept@^2.2.4: version "2.2.5" - resolved "https://registry.yarnpkg.com/attr-accept/-/attr-accept-2.2.5.tgz#d7061d958e6d4f97bf8665c68b75851a0713ab5e" + resolved "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.5.tgz" integrity sha512-0bDNnY/u6pPwHDMoF0FieU354oBi0a8rD9FcsLwzcGWbc8KS8KPIi7y+s13OlVY+gMWc/9xEMUgNE6Qm8ZllYQ== autoprefixer@^10.4.18: @@ -1610,7 +1692,7 @@ braces@^3.0.3, braces@~3.0.2: dependencies: fill-range "^7.1.1" -browserslist@^4.23.3, browserslist@^4.24.0, browserslist@^4.24.3: +browserslist@^4.23.3, browserslist@^4.24.0, browserslist@^4.24.3, "browserslist@>= 4.21.0": version "4.24.4" resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz" integrity sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A== @@ -1622,7 +1704,7 @@ browserslist@^4.23.3, browserslist@^4.24.0, browserslist@^4.24.3: bson@^5.5.0: version "5.5.1" - resolved "https://registry.yarnpkg.com/bson/-/bson-5.5.1.tgz#f5849d405711a7f23acdda9a442375df858e6833" + resolved "https://registry.npmjs.org/bson/-/bson-5.5.1.tgz" integrity sha512-ix0EwukN2EpC0SRWIj/7B5+A6uQMQy6KMREI9qQqvgpkV2frH63T0UDVd1SYedL6dNCmDBYB3QtXi4ISk9YT+g== buffer-equal-constant-time@^1.0.1: @@ -1771,7 +1853,7 @@ convert-source-map@^2.0.0: cookie@^0.7.0: version "0.7.2" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" + resolved "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz" integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== core-js-compat@^3.34.0: @@ -1781,7 +1863,7 @@ core-js-compat@^3.34.0: dependencies: browserslist "^4.24.3" -cross-spawn@^7.0.0, cross-spawn@^7.0.6: +cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.6: version "7.0.6" resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz" integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== @@ -1800,7 +1882,7 @@ csstype@^3.0.2: resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz" integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== -"d3-array@2 - 3", "d3-array@2.10.0 - 3", d3-array@^3.1.6: +d3-array@^3.1.6, "d3-array@2 - 3", "d3-array@2.10.0 - 3": version "3.2.4" resolved "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz" integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg== @@ -1822,7 +1904,7 @@ d3-ease@^3.0.1: resolved "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz" integrity sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg== -"d3-interpolate@1.2.0 - 3", d3-interpolate@^3.0.1: +d3-interpolate@^3.0.1, "d3-interpolate@1.2.0 - 3": version "3.0.1" resolved "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz" integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g== @@ -1859,7 +1941,7 @@ d3-shape@^3.1.0: dependencies: d3-time "1 - 3" -"d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@^3.0.0: +d3-time@^3.0.0, "d3-time@1 - 3", "d3-time@2.1.1 - 3": version "3.1.0" resolved "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz" integrity sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q== @@ -1905,16 +1987,9 @@ data-view-byte-offset@^1.0.1: date-fns@^4.1.0, date-fns@^4.4.0: version "4.4.0" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-4.4.0.tgz#806539edf45c616b2b76b5f78b88c56ed3c7e036" + resolved "https://registry.npmjs.org/date-fns/-/date-fns-4.4.0.tgz" integrity sha512-+1UMbeh68lH1SegH83CGWwpb6OHHbpSgr3+s5Eww5M4CAgswBpoWS0AjTOfEJ33HiYKz1hdj/KTFprzXHmq/6w== -debug@4, debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.7: - version "4.4.0" - resolved "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz" - integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== - dependencies: - ms "^2.1.3" - debug@^3.2.7: version "3.2.7" resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz" @@ -1922,6 +1997,13 @@ debug@^3.2.7: dependencies: ms "^2.1.1" +debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.7, debug@4: + version "4.4.0" + resolved "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz" + integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== + dependencies: + ms "^2.1.3" + decimal.js-light@^2.5.1: version "2.5.1" resolved "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz" @@ -1994,6 +2076,13 @@ doctrine@^2.1.0: dependencies: esutils "^2.0.2" +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + dotenv@16.0.3: version "16.0.3" resolved "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz" @@ -2023,7 +2112,7 @@ eastasianwidth@^0.2.0: resolved "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz" integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== -ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11: +ecdsa-sig-formatter@^1.0.11, ecdsa-sig-formatter@1.0.11: version "1.0.11" resolved "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz" integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== @@ -2194,6 +2283,38 @@ es-toolkit@^1.39.3: resolved "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.46.1.tgz" integrity sha512-5eNtXOs3tbfxXOj04tjjseeWkRWaoCjdEI+96DgwzZoe6c9juL49pXlzAFTI72aWC9Y8p7168g6XIKjh7k6pyQ== +esbuild@~0.28.0: + version "0.28.1" + resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz" + integrity sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw== + optionalDependencies: + "@esbuild/aix-ppc64" "0.28.1" + "@esbuild/android-arm" "0.28.1" + "@esbuild/android-arm64" "0.28.1" + "@esbuild/android-x64" "0.28.1" + "@esbuild/darwin-arm64" "0.28.1" + "@esbuild/darwin-x64" "0.28.1" + "@esbuild/freebsd-arm64" "0.28.1" + "@esbuild/freebsd-x64" "0.28.1" + "@esbuild/linux-arm" "0.28.1" + "@esbuild/linux-arm64" "0.28.1" + "@esbuild/linux-ia32" "0.28.1" + "@esbuild/linux-loong64" "0.28.1" + "@esbuild/linux-mips64el" "0.28.1" + "@esbuild/linux-ppc64" "0.28.1" + "@esbuild/linux-riscv64" "0.28.1" + "@esbuild/linux-s390x" "0.28.1" + "@esbuild/linux-x64" "0.28.1" + "@esbuild/netbsd-arm64" "0.28.1" + "@esbuild/netbsd-x64" "0.28.1" + "@esbuild/openbsd-arm64" "0.28.1" + "@esbuild/openbsd-x64" "0.28.1" + "@esbuild/openharmony-arm64" "0.28.1" + "@esbuild/sunos-x64" "0.28.1" + "@esbuild/win32-arm64" "0.28.1" + "@esbuild/win32-ia32" "0.28.1" + "@esbuild/win32-x64" "0.28.1" + escalade@^3.2.0: version "3.2.0" resolved "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz" @@ -2280,7 +2401,7 @@ eslint-plugin-eslint-comments@^3.2.0: escape-string-regexp "^1.0.5" ignore "^5.0.5" -eslint-plugin-import@^2.29.1, eslint-plugin-import@^2.31.0: +eslint-plugin-import@*, eslint-plugin-import@^2.29.1, eslint-plugin-import@^2.31.0, eslint-plugin-import@>=1.4.0: version "2.31.0" resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz" integrity sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A== @@ -2305,7 +2426,7 @@ eslint-plugin-import@^2.29.1, eslint-plugin-import@^2.31.0: string.prototype.trimend "^1.0.8" tsconfig-paths "^3.15.0" -eslint-plugin-jest@^27.9.0: +eslint-plugin-jest@^27.9.0, eslint-plugin-jest@>=25: version "27.9.0" resolved "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz" integrity sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug== @@ -2430,7 +2551,7 @@ eslint-plugin-vitest@^0.3.22: dependencies: "@typescript-eslint/utils" "^7.1.1" -eslint-scope@5.1.1, eslint-scope@^5.1.1: +eslint-scope@^5.1.1, eslint-scope@5.1.1: version "5.1.1" resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== @@ -2438,6 +2559,14 @@ eslint-scope@5.1.1, eslint-scope@^5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" +eslint-scope@^7.2.2: + version "7.2.2" + resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + eslint-scope@^8.4.0: version "8.4.0" resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz" @@ -2466,6 +2595,50 @@ eslint-visitor-keys@^4.2.1: resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz" integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== +eslint@*, "eslint@^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7", "eslint@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0", "eslint@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0", "eslint@^6.0.0 || ^7.0.0 || ^8.0.0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^7.0.0 || ^8.0.0", "eslint@^7.23.0 || ^8.0.0 || ^9.0.0", "eslint@^7.5.0 || ^8.0.0 || ^9.0.0", eslint@^8.56.0, "eslint@^8.57.0 || ^9.0.0", eslint@^9.10.0, eslint@>=4.19.1, eslint@>=7.0.0, eslint@>=8.0.0, eslint@>=8.40.0, "eslint@>=8.48.0 <9", eslint@>=8.56.0, eslint@>6.6.0: + version "8.57.1" + resolved "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz" + integrity sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.6.1" + "@eslint/eslintrc" "^2.1.4" + "@eslint/js" "8.57.1" + "@humanwhocodes/config-array" "^0.13.0" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + "@ungap/structured-clone" "^1.2.0" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.2.2" + eslint-visitor-keys "^3.4.3" + espree "^9.6.1" + esquery "^1.4.2" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + graphemer "^1.4.0" + ignore "^5.2.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + strip-ansi "^6.0.1" + text-table "^0.2.0" + eslint@^9.14.0: version "9.39.2" resolved "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz" @@ -2515,7 +2688,7 @@ espree@^10.0.1, espree@^10.4.0: acorn-jsx "^5.3.2" eslint-visitor-keys "^4.2.1" -espree@^9.6.0: +espree@^9.6.0, espree@^9.6.1: version "9.6.1" resolved "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz" integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== @@ -2524,7 +2697,7 @@ espree@^9.6.0: acorn-jsx "^5.3.2" eslint-visitor-keys "^3.4.1" -esquery@^1.5.0: +esquery@^1.4.2, esquery@^1.5.0: version "1.6.0" resolved "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz" integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== @@ -2573,27 +2746,27 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@3.3.1: - version "3.3.1" - resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz" - integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== +fast-glob@^3.2.9, fast-glob@^3.3.2: + version "3.3.3" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz" + integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" glob-parent "^5.1.2" merge2 "^1.3.0" - micromatch "^4.0.4" + micromatch "^4.0.8" -fast-glob@^3.2.9, fast-glob@^3.3.2: - version "3.3.3" - resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz" - integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== +fast-glob@3.3.1: + version "3.3.1" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz" + integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" glob-parent "^5.1.2" merge2 "^1.3.0" - micromatch "^4.0.8" + micromatch "^4.0.4" fast-json-stable-stringify@^2.0.0: version "2.1.0" @@ -2636,6 +2809,13 @@ fdir@^6.4.2: resolved "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz" integrity sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw== +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + file-entry-cache@^8.0.0: version "8.0.0" resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz" @@ -2645,7 +2825,7 @@ file-entry-cache@^8.0.0: file-selector@^2.1.0: version "2.1.2" - resolved "https://registry.yarnpkg.com/file-selector/-/file-selector-2.1.2.tgz#fe7c7ee9e550952dfbc863d73b14dc740d7de8b4" + resolved "https://registry.npmjs.org/file-selector/-/file-selector-2.1.2.tgz" integrity sha512-QgXo+mXTe8ljeqUFaX3QVHc5osSItJ/Km+xpocx0aSqWGMSCf6qYs/VnzZgS864Pjn5iceMRFigeAV7AfTlaig== dependencies: tslib "^2.7.0" @@ -2673,6 +2853,15 @@ find-up@^5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" +flat-cache@^3.0.4: + version "3.2.0" + resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz" + integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.3" + rimraf "^3.0.2" + flat-cache@^4.0.0: version "4.0.1" resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz" @@ -2718,7 +2907,12 @@ fraction.js@^4.3.7: resolved "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz" integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew== -fsevents@~2.3.2: +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2, fsevents@~2.3.3: version "2.3.3" resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== @@ -2839,17 +3033,6 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" -glob@10.3.10: - version "10.3.10" - resolved "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz" - integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g== - dependencies: - foreground-child "^3.1.0" - jackspeak "^2.3.5" - minimatch "^9.0.1" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - path-scurry "^1.10.1" - glob@^10.3.10: version "10.4.5" resolved "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz" @@ -2862,6 +3045,29 @@ glob@^10.3.10: package-json-from-dist "^1.0.0" path-scurry "^1.11.1" +glob@^7.1.3: + version "7.2.3" + resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@10.3.10: + version "10.3.10" + resolved "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz" + integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g== + dependencies: + foreground-child "^3.1.0" + jackspeak "^2.3.5" + minimatch "^9.0.1" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + path-scurry "^1.10.1" + globals@^11.1.0: version "11.12.0" resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" @@ -3060,7 +3266,15 @@ indent-string@^4.0.0: resolved "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== -inherits@^2.0.3: +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@^2.0.3, inherits@2: version "2.0.4" resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -3081,7 +3295,7 @@ internal-slot@^1.1.0: ip-address@^10.1.1: version "10.2.0" - resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-10.2.0.tgz#805fc178b20c518bd4c8548b24fe30892d7f3206" + resolved "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz" integrity sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA== is-array-buffer@^3.0.4, is-array-buffer@^3.0.5: @@ -3226,6 +3440,11 @@ is-number@^7.0.0: resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + is-plain-obj@^4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz" @@ -3342,7 +3561,7 @@ jackspeak@^3.1.2: optionalDependencies: "@pkgjs/parseargs" "^0.11.0" -jiti@^1.21.6: +jiti@*, jiti@^1.21.6: version "1.21.7" resolved "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz" integrity sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A== @@ -3354,7 +3573,7 @@ jju@~1.4.0: jose@^4.15.5, jose@^4.15.9: version "4.15.9" - resolved "https://registry.yarnpkg.com/jose/-/jose-4.15.9.tgz#9b68eda29e9a0614c042fa29387196c7dd800100" + resolved "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz" integrity sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA== "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: @@ -3445,7 +3664,7 @@ jws@^4.0.0: jwa "^2.0.1" safe-buffer "^5.0.1" -keyv@^4.5.4: +keyv@^4.5.3, keyv@^4.5.4: version "4.5.4" resolved "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz" integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== @@ -3482,6 +3701,16 @@ lines-and-columns@^1.1.6: resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== +"live@file:/Users/adityapathak/core/apps/live": + version "1.0.0" + resolved "file:apps/live" + dependencies: + "@repo/ui" "*" + "@repo/util" "*" + next "^14.2.3" + react "^18.2.0" + react-dom "^18.2.0" + locate-path@^5.0.0: version "5.0.0" resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" @@ -3527,7 +3756,7 @@ lru-cache@^5.1.1: lru-cache@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== dependencies: yallist "^4.0.0" @@ -3537,6 +3766,16 @@ lucide-react@^1.14.0: resolved "https://registry.npmjs.org/lucide-react/-/lucide-react-1.16.0.tgz" integrity sha512-dYwyPzb4MEKpGUmNYk3WKWPnMrHs3FKM+q94kAnJrcDIqqn1hq2xY8scaS2ovsOCM5D51ey2gaRG3PBb1vgoYQ== +"main@file:/Users/adityapathak/core/apps/main": + version "1.0.0" + resolved "file:apps/main" + dependencies: + "@repo/ui" "*" + "@repo/util" "*" + next "^14.2.3" + react "^18.2.0" + react-dom "^18.2.0" + math-intrinsics@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz" @@ -3582,14 +3821,21 @@ min-indent@^1.0.0: resolved "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== -minimatch@^3.1.2: +minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" -minimatch@^9.0.1, minimatch@^9.0.4: +minimatch@^9.0.1: + version "9.0.5" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^9.0.4: version "9.0.5" resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz" integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== @@ -3608,15 +3854,15 @@ minimist@^1.2.0, minimist@^1.2.6: mongodb-connection-string-url@^2.6.0: version "2.6.0" - resolved "https://registry.yarnpkg.com/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz#57901bf352372abdde812c81be47b75c6b2ec5cf" + resolved "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz" integrity sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ== dependencies: "@types/whatwg-url" "^8.2.1" whatwg-url "^11.0.0" -mongodb@^5.9.2: +"mongodb@^5 || ^4", mongodb@^5.9.2: version "5.9.2" - resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-5.9.2.tgz#39a73b9fbc87ac9d9c1aaf8aab5c5bb69e2b913e" + resolved "https://registry.npmjs.org/mongodb/-/mongodb-5.9.2.tgz" integrity sha512-H60HecKO4Bc+7dhOv4sJlgvenK4fQNqqUIlXxZYQNbfEWSALGAwGoyJd/0Qwk4TttFXUOHJ2ZJQe/52ScaUwtQ== dependencies: bson "^5.5.0" @@ -3649,9 +3895,9 @@ natural-compare@^1.4.0: resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -next-auth@^4.24.14: +next-auth@^4, next-auth@^4.24.14: version "4.24.14" - resolved "https://registry.yarnpkg.com/next-auth/-/next-auth-4.24.14.tgz#c14916e215f8f4aef2358e694bd14c40212139b2" + resolved "https://registry.npmjs.org/next-auth/-/next-auth-4.24.14.tgz" integrity sha512-YRz6xFDXKUwiXSMMChbrBEWyFktZ1qZXEgeSHQQ3nsy08B4c/xLk6REeutRsIFwkjY/1+ShHnu07DN3JeJguig== dependencies: "@babel/runtime" "^7.20.13" @@ -3664,7 +3910,7 @@ next-auth@^4.24.14: preact-render-to-string "^5.1.19" uuid "^8.3.2" -next@^14.2.3: +"next@^12.2.5 || ^13 || ^14 || ^15 || ^16", next@^14.2.3: version "14.2.35" resolved "https://registry.npmjs.org/next/-/next-14.2.35.tgz" integrity sha512-KhYd2Hjt/O1/1aZVX3dCwGXM1QmOV4eNM2UTacK5gipDdPN/oHHK/4oVGy7X8GMfPMsUTUEmGlsy0EY1YGAkig== @@ -3699,10 +3945,10 @@ node-releases@^2.0.19: resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz" integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== -nodemailer@^9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-9.0.1.tgz#871c04d8423fc0c790289f4a8f6f71f1b3563e8c" - integrity sha512-Gwv8SQewT616ZM/URn0H54b8PWo/Wum7md3EW2aWy1lO27+WZCX+Xyak3J+NlmHUjDh5ME+uesJUDRbR3Ye8Bw== +nodemailer@^7.0.7: + version "7.0.13" + resolved "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.13.tgz" + integrity sha512-PNDFSJdP+KFgdsG3ZzMXCgquO7I6McjY2vlqILjtJd0hy8wEvtugS9xKRF2NWlPNGxvLCXlTNIae4serI7dinw== normalize-package-data@^2.5.0: version "2.5.0" @@ -3726,7 +3972,7 @@ normalize-range@^0.1.2: oauth@^0.9.15: version "0.9.15" - resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1" + resolved "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz" integrity sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA== object-assign@^4.0.1, object-assign@^4.1.1: @@ -3736,7 +3982,7 @@ object-assign@^4.0.1, object-assign@^4.1.1: object-hash@^2.2.0: version "2.2.0" - resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5" + resolved "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz" integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw== object-hash@^3.0.0: @@ -3806,10 +4052,10 @@ object.values@^1.1.6, object.values@^1.2.0, object.values@^1.2.1: oidc-token-hash@^5.0.3: version "5.2.0" - resolved "https://registry.yarnpkg.com/oidc-token-hash/-/oidc-token-hash-5.2.0.tgz#be8a8885c7e2478d21a674e15afa31f1bcc4a61f" + resolved "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.2.0.tgz" integrity sha512-6gj2m8cJZ+iSW8bm0FXdGF0YhIQbKrfP4yWTNzxc31U6MOjfEmB1rHvlYvxI1B7t7BCi1F2vYTT6YhtQRG4hxw== -once@^1.4.0: +once@^1.3.0, once@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== @@ -3818,7 +4064,7 @@ once@^1.4.0: openid-client@^5.4.0: version "5.7.1" - resolved "https://registry.yarnpkg.com/openid-client/-/openid-client-5.7.1.tgz#34cace862a3e6472ed7d0a8616ef73b7fb85a9c3" + resolved "https://registry.npmjs.org/openid-client/-/openid-client-5.7.1.tgz" integrity sha512-jDBPgSVfTnkIh71Hg9pRvtJc6wTwqjRkN88+gCFtYWrlP4Yx2Dsrow8uPi3qLr/aeymPF3o2+dS+wOpglK04ew== dependencies: jose "^4.15.9" @@ -3912,6 +4158,11 @@ path-expression-matcher@^1.5.0: resolved "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.5.0.tgz" integrity sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ== +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + path-key@^3.1.0: version "3.1.1" resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" @@ -3945,7 +4196,7 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -picomatch@^4.0.2: +"picomatch@^3 || ^4", picomatch@^4.0.2: version "4.0.2" resolved "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz" integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== @@ -4014,6 +4265,15 @@ postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0: resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== +postcss@^8.0.0, postcss@^8.1.0, postcss@^8.2.14, postcss@^8.4.21, postcss@^8.4.35, postcss@^8.4.47, postcss@>=8.0.9: + version "8.5.1" + resolved "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz" + integrity sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ== + dependencies: + nanoid "^3.3.8" + picocolors "^1.1.1" + source-map-js "^1.2.1" + postcss@8.4.31: version "8.4.31" resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz" @@ -4023,26 +4283,17 @@ postcss@8.4.31: picocolors "^1.0.0" source-map-js "^1.0.2" -postcss@^8.4.35, postcss@^8.4.47: - version "8.5.1" - resolved "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz" - integrity sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ== - dependencies: - nanoid "^3.3.8" - picocolors "^1.1.1" - source-map-js "^1.2.1" - -preact-render-to-string@^5.1.19: +preact-render-to-string@^5.1.19, preact-render-to-string@>=5: version "5.2.6" - resolved "https://registry.yarnpkg.com/preact-render-to-string/-/preact-render-to-string-5.2.6.tgz#0ff0c86cd118d30affb825193f18e92bd59d0604" + resolved "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-5.2.6.tgz" integrity sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw== dependencies: pretty-format "^3.8.0" -preact@^10.6.3: - version "10.29.3" - resolved "https://registry.yarnpkg.com/preact/-/preact-10.29.3.tgz#36f96b7a8edc2fccea76daa5e7545597dc15ab28" - integrity sha512-D9NL1GAnJZhc3RndVs4gDdxEeU9TcHgywMrhhOsnpdlvFjdbx0gAsLUnH6JEhlJH5giL7Tx5biWPUSEXE/HPzw== +preact@^10.6.3, preact@>=10: + version "10.29.7" + resolved "https://registry.npmjs.org/preact/-/preact-10.29.7.tgz" + integrity sha512-DCHYrK/B10yUD3ZjLfhZ3WIE/9Vf9VFUODcRE2dRomTYDpJk6z6L9wecSfhfE6M9ZTHUdyQkoC46arIDhEV84Q== prelude-ls@^1.2.1: version "1.2.1" @@ -4062,14 +4313,14 @@ prettier-plugin-tailwindcss@^0.5.11: resolved "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.5.14.tgz" integrity sha512-Puaz+wPUAhFp8Lo9HuciYKM2Y2XExESjeT+9NQoVFXZsPPnc9VYss2SpxdQ6vbatmt8/4+SN0oe0I1cPDABg9Q== -prettier@^3.2.5: +prettier@^3.0, prettier@^3.2.5, "prettier@>= 1.16.0", "prettier@>=3.0.0 <4": version "3.4.2" resolved "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz" integrity sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ== pretty-format@^3.8.0: version "3.8.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-3.8.0.tgz#bfbed56d5e9a776645f4b1ff7aa1a3ac4fa3c385" + resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz" integrity sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew== prop-types@^15.8.1: @@ -4093,13 +4344,13 @@ queue-microtask@^1.2.2: react-day-picker@^10.0.1: version "10.0.1" - resolved "https://registry.yarnpkg.com/react-day-picker/-/react-day-picker-10.0.1.tgz#8498e3f0ace2e9d03c209a5458c451a377c2d85c" + resolved "https://registry.npmjs.org/react-day-picker/-/react-day-picker-10.0.1.tgz" integrity sha512-eNh6BlwcYInWaJtRv18mXQ06Ys/H6rdTZAnTaSdOYJuTpwP1JMCHNd1FDRadA+gbeinq+psdULN5Xnowy9mV8w== dependencies: "@date-fns/tz" "^1.4.1" date-fns "^4.1.0" -react-dom@^18.2.0: +"react-dom@^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom@^17.0.2 || ^18 || ^19", "react-dom@^18.0.0 || ^19.0.0 || ^19.0.0-rc", react-dom@^18.2.0, react-dom@>=16.8, react-dom@>=16.8.0: version "18.3.1" resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz" integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw== @@ -4109,14 +4360,14 @@ react-dom@^18.2.0: react-dropzone@^15.0.0: version "15.0.0" - resolved "https://registry.yarnpkg.com/react-dropzone/-/react-dropzone-15.0.0.tgz#bd03c7c2b14fe4ea9db1a9c74502b85339f2e505" + resolved "https://registry.npmjs.org/react-dropzone/-/react-dropzone-15.0.0.tgz" integrity sha512-lGjYV/EoqEjEWPnmiSvH4v5IoIAwQM2W4Z1C0Q/Pw2xD0eVzKPS359BQTUMum+1fa0kH2nrKjuavmTPOGhpLPg== dependencies: attr-accept "^2.2.4" file-selector "^2.1.0" prop-types "^15.8.1" -react-hook-form@^7.75.0: +react-hook-form@^7.55.0, react-hook-form@^7.75.0: version "7.76.0" resolved "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.76.0.tgz" integrity sha512-eKtLGgFeSgkHqQD8J59AMZ9a4uD1D83iSIzt4YlTGD7liDen5rrjcUO1rVIGd9yC1gofryjtHbv+4ny4hkLWlw== @@ -4126,12 +4377,12 @@ react-icons@^5.0.0, react-icons@^5.5.0: resolved "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz" integrity sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw== -react-is@^16.13.1: +react-is@^16.13.1, "react-is@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0": version "16.13.1" resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -"react-redux@8.x.x || 9.x.x": +"react-redux@^7.2.1 || ^8.1.3 || ^9.0.0", "react-redux@8.x.x || 9.x.x": version "9.3.0" resolved "https://registry.npmjs.org/react-redux/-/react-redux-9.3.0.tgz" integrity sha512-KQopgqFo/p/fgmAs5qz6p5RWaNAzq40WAu7fJIXnQpYxFPbJYtsJPWvGeF2rOBaY/kEuV77AVsX8TsQzKm+A/g== @@ -4166,7 +4417,7 @@ react-style-singleton@^2.2.2, react-style-singleton@^2.2.3: get-nonce "^1.0.0" tslib "^2.0.0" -react@^18.2.0: +react@*, "react@^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8 || ^17 || ^18 || ^19", "react@^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react@^16.8.0 || ^17 || ^18 || ^19 || ^19.0.0-rc", "react@^16.8.0 || ^17 || ^18 || ^19", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react@^16.9.0 || ^17.0.0 || ^18 || ^19", "react@^17.0.2 || ^18 || ^19", "react@^18.0 || ^19", "react@^18.0.0 || ^19.0.0 || ^19.0.0-rc", react@^18.2.0, react@^18.3.1, "react@>= 16.8 || 18.0.0", "react@>= 16.8.0 || 17.x.x || ^18.0.0-0", react@>=16.8, react@>=16.8.0: version "18.3.1" resolved "https://registry.npmjs.org/react/-/react-18.3.1.tgz" integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== @@ -4237,7 +4488,7 @@ redux-thunk@^3.1.0: resolved "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz" integrity sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw== -redux@^5.0.1: +redux@^5.0.0, redux@^5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz" integrity sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w== @@ -4280,7 +4531,7 @@ regjsparser@^0.10.0: dependencies: jsesc "~0.5.0" -reselect@5.1.1, reselect@^5.1.0: +reselect@^5.1.0, reselect@5.1.1: version "5.1.1" resolved "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz" integrity sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w== @@ -4340,6 +4591,13 @@ reusify@^1.0.4: resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" @@ -4387,11 +4645,6 @@ scheduler@^0.23.2: dependencies: loose-envify "^1.1.0" -"semver@2 || 3 || 4 || 5": - version "5.7.2" - resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz" - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== - semver@^6.3.1: version "6.3.1" resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" @@ -4402,9 +4655,14 @@ semver@^7.3.7, semver@^7.5.4, semver@^7.6.0, semver@^7.6.3: resolved "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz" integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== +"semver@2 || 3 || 4 || 5": + version "5.7.2" + resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + server-only@^0.0.1: version "0.0.1" - resolved "https://registry.yarnpkg.com/server-only/-/server-only-0.0.1.tgz#0f366bb6afb618c37c9255a314535dc412cd1c9e" + resolved "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz" integrity sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA== set-function-length@^1.2.2: @@ -4502,12 +4760,12 @@ slash@^3.0.0: smart-buffer@^4.2.0: version "4.2.0" - resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" + resolved "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz" integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== socks@^2.7.1: version "2.8.9" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.8.9.tgz#aa5f130ca0f88a43fa44faf4869c50d22aa27752" + resolved "https://registry.npmjs.org/socks/-/socks-2.8.9.tgz" integrity sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw== dependencies: ip-address "^10.1.1" @@ -4597,6 +4855,13 @@ streamsearch@^1.1.0: resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz" integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + "string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" @@ -4692,13 +4957,6 @@ string.prototype.trimstart@^1.0.8: define-properties "^1.2.1" es-object-atoms "^1.0.0" -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - "strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" @@ -4797,7 +5055,7 @@ tailwindcss-animated@^1.1.2: resolved "https://registry.npmjs.org/tailwindcss-animated/-/tailwindcss-animated-1.1.2.tgz" integrity sha512-SI4owS5ojserhgEYIZA/uFVdNjU2GMB2P3sjtjmFA52VxoUi+Hht6oR5+RdT+CxrX9cNNYEa+vbTWHvN9zbj3w== -tailwindcss@^3.4.1: +tailwindcss@^3.4.1, tailwindcss@>=3.1.0: version "3.4.17" resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz" integrity sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og== @@ -4841,6 +5099,11 @@ teeny-request@^9.0.0: stream-events "^1.0.5" uuid "^9.0.0" +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + thenify-all@^1.0.0: version "1.6.0" resolved "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz" @@ -4877,7 +5140,7 @@ to-regex-range@^5.0.1: tr46@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-3.0.0.tgz#555c4e297a950617e8eeddef633c87d4d9d6cbf9" + resolved "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz" integrity sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA== dependencies: punycode "^2.1.1" @@ -4929,37 +5192,21 @@ tsutils@^3.21.0: dependencies: tslib "^1.8.1" +tsx@^4.19.2: + version "4.23.1" + resolved "https://registry.npmjs.org/tsx/-/tsx-4.23.1.tgz" + integrity sha512-GQHnkIfxyx1wYCOS/wonik5MVRZU9hi1TEZmzGZSCJB1y9YgoZ8H6itNE/u4suE+yLmOzuE4E5S4TZ/ZX2wcWQ== + dependencies: + esbuild "~0.28.0" + optionalDependencies: + fsevents "~2.3.3" + turbo-darwin-64@2.4.0: version "2.4.0" resolved "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-2.4.0.tgz" integrity sha512-kVMScnPUa3R4n7woNmkR15kOY0aUwCLJcUyH5UC59ggKqr5HIHwweKYK8N1pwBQso0LQF4I9i93hIzfJguCcwQ== -turbo-darwin-arm64@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/turbo-darwin-arm64/-/turbo-darwin-arm64-2.4.0.tgz#7c8a6d612056ed2d841e5de3cbbdd8b7d1c7ad84" - integrity sha512-8JObIpfun1guA7UlFR5jC/SOVm49lRscxMxfg5jZ5ABft79rhFC+ygN9AwAhGKv6W2DUhIh2xENkSgu4EDmUyg== - -turbo-linux-64@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/turbo-linux-64/-/turbo-linux-64-2.4.0.tgz#6d24123685db82ff5c863e2c96c976394d13c8b3" - integrity sha512-xWDGGcRlBuGV7HXWAVuTY6vsQi4aZxGMAnuiuNDg8Ij1aHGohOM0RUsWMXjxz4vuJmjk9+/D6NQqHH3AJEXezg== - -turbo-linux-arm64@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/turbo-linux-arm64/-/turbo-linux-arm64-2.4.0.tgz#f286a91c8c1f25074f383870ff597c3b3227871b" - integrity sha512-c3En99xMguc/Pdtk/rZP53LnDdw0W6lgUc04he8r8F+UHYSNvgzHh0WGXXmCC6lGbBH72kPhhGx4bAwyvi7dug== - -turbo-windows-64@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/turbo-windows-64/-/turbo-windows-64-2.4.0.tgz#60c3fdb38f7fb3fcce3acf07256c5f9973072bc5" - integrity sha512-/gOORuOlyA8JDPzyA16CD3wvyRcuBFePa1URAnFUof9hXQmKxK0VvSDO79cYZFsJSchCKNJpckUS0gYxGsWwoA== - -turbo-windows-arm64@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/turbo-windows-arm64/-/turbo-windows-arm64-2.4.0.tgz#23809ecfdd31e5800174f0af23f8f35b2f0370d4" - integrity sha512-/DJIdTFijEMM5LSiEpSfarDOMOlYqJV+EzmppqWtHqDsOLF4hbbIBH9sJR6OOp5dURAu5eURBYdmvBRz9Lo6TA== - -turbo@^2.2.3: +turbo@^2.2.3, turbo@>2.0.0: version "2.4.0" resolved "https://registry.npmjs.org/turbo/-/turbo-2.4.0.tgz" integrity sha512-ah/yQp2oMif1X0u7fBJ4MLMygnkbKnW5O8SG6pJvloPCpHfFoZctkSVQiJ3VnvNTq71V2JJIdwmOeu1i34OQyg== @@ -5047,7 +5294,7 @@ typescript-eslint@^8.13.0: "@typescript-eslint/parser" "8.23.0" "@typescript-eslint/utils" "8.23.0" -typescript@5.5.4: +"typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta", typescript@>=3.3.1, typescript@>=4.2.0, "typescript@>=4.8.0 <6", typescript@>=4.8.4, "typescript@>=4.8.4 <5.8.0", typescript@5.5.4: version "5.5.4" resolved "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz" integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q== @@ -5119,7 +5366,17 @@ uuid@^14.0.0: resolved "https://registry.npmjs.org/uuid/-/uuid-14.0.0.tgz" integrity sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg== -uuid@^9.0.0, uuid@^9.0.1: +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +uuid@^9.0.0: + version "9.0.1" + resolved "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + +uuid@^9.0.1: version "9.0.1" resolved "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz" integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== @@ -5164,7 +5421,7 @@ webidl-conversions@^7.0.0: whatwg-url@^11.0.0: version "11.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-11.0.0.tgz#0a849eebb5faf2119b901bb76fd795c2848d4018" + resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz" integrity sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ== dependencies: tr46 "^3.0.0" @@ -5277,7 +5534,7 @@ yallist@^3.0.2: yallist@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== yaml@^2.3.4: From ca75610eebf7532ad94ac1198ad396a9e844b141 Mon Sep 17 00:00:00 2001 From: adityapat24 Date: Wed, 15 Jul 2026 14:01:34 -0400 Subject: [PATCH 12/12] remove uneused var --- apps/app-portal/src/lib/db.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/app-portal/src/lib/db.ts b/apps/app-portal/src/lib/db.ts index b1443814..75cbc327 100644 --- a/apps/app-portal/src/lib/db.ts +++ b/apps/app-portal/src/lib/db.ts @@ -1,7 +1,5 @@ import { Db, MongoClient } from "mongodb"; -const DEFAULT_DBNAME = "HackbeanpotCluster"; - function resolveUri(): string { const uri = process.env.MONGO_PROD_CONNECTION_STRING; if (!uri) { @@ -13,7 +11,6 @@ function resolveUri(): string { } const uri = resolveUri(); -const dbName = process.env.MONGO_SERVER_DBNAME ?? DEFAULT_DBNAME; declare global { // eslint-disable-next-line no-var
+ Sign in to HackBeanpot @@ -34,16 +33,16 @@
+ Or copy and paste this link into your browser:
{{url}}
+ If you did not request this email you can safely ignore it.