import { NextRequest, NextResponse } from "next/server"; import { auth } from "./lib/auth/server"; import { createMatcher } from "./lib/utils"; const authUrlsPatterns = [ "/sign-in", "/sign-up", "/forgot-password", "/reset-password", ]; const openRoute = ["/"]; const protectedRoutes = ["/get-started", "/[slug]", "/[slug]/**"]; // Create matchers once to avoid recreating on every request const openRouteMatcher = createMatcher(openRoute); const protectedRouteMatcher = createMatcher(protectedRoutes); const authRouteMatcher = createMatcher(authUrlsPatterns); export const middleware = async (request: NextRequest) => { const session = await auth.api.getSession(request); // Skip middleware logic for API routes if ( request.nextUrl.pathname.startsWith("/api") || request.nextUrl.pathname.startsWith("/trpc") || request.nextUrl.pathname.startsWith("/rpc") ) { return NextResponse.next(); } const openRouteResult = openRouteMatcher.match(request.nextUrl.pathname); if (openRouteResult?.matched && openRouteResult?.pattern === "/") { return NextResponse.next(); } const protectedMatchResult = protectedRouteMatcher.match( request.nextUrl.pathname ); const authMatchResult = authRouteMatcher.match(request.nextUrl.pathname); if (!session && protectedMatchResult?.matched && !authMatchResult.matched) { return NextResponse.redirect(new URL("/sign-in", request.url)); } if ( session && (authMatchResult?.matched || (protectedMatchResult?.matched && protectedMatchResult?.pattern === "/get-started")) ) { const getActiveOrganization = await auth.api.getFullOrganization({ query: { organizationId: session.session.activeOrganizationId || undefined, }, headers: request.headers, }); if (!!getActiveOrganization) { return NextResponse.redirect( new URL(`/${getActiveOrganization.slug}`, request.url) ); } return NextResponse.next(); } if (session && protectedMatchResult?.matched) { const slug = protectedMatchResult?.params?.slug || protectedMatchResult?.segments?.[0]; const listOrganization = await auth.api.listOrganizations({ headers: request.headers, }); let organization = listOrganization.find((org) => org.slug === slug); if (!organization && listOrganization.length <= 0) { return NextResponse.redirect(new URL("/get-started", request.url)); } if (!organization && listOrganization.length > 0) { organization = listOrganization[0]; return NextResponse.redirect( new URL(`/${listOrganization[0].slug}`, request.url) ); } // remove this when better-auth has this functionality working if (organization) { auth.api.setActiveOrganization({ body: { organizationId: organization?.id, organizationSlug: organization?.slug, }, request, headers: request.headers, }); } } return NextResponse.next(); }; export const config = { matcher: [ "/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)", "/(api|trpc|rpc)(.*)", ], runtime: "nodejs", };