diff --git a/.changeset/grumpy-otters-kneel.md b/.changeset/grumpy-otters-kneel.md new file mode 100644 index 0000000000..0c34bb11e0 --- /dev/null +++ b/.changeset/grumpy-otters-kneel.md @@ -0,0 +1,5 @@ +--- +"create-t3-app": minor +--- + +update to next.js 15 and next-auth v5 diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 6d3d590996..ae0d0fc562 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -61,9 +61,9 @@ jobs: - run: cd ../ci-${{ matrix.trpc }}-${{ matrix.tailwind }}-${{ matrix.nextAuth }}-${{ matrix.prisma }}-${{ matrix.drizzle}}-${{ matrix.appRouter }}-${{ matrix.dbType }} && pnpm build if: ${{ steps.matrix-valid.outputs.continue == 'true' }} env: - NEXTAUTH_SECRET: foo - DISCORD_CLIENT_ID: bar - DISCORD_CLIENT_SECRET: baz + AUTH_SECRET: foo + AUTH_DISCORD_ID: bar + AUTH_DISCORD_SECRET: baz SKIP_ENV_VALIDATION: true build-t3-app-with-bun: @@ -101,7 +101,7 @@ jobs: - run: cd ../ci-bun && bun run build # - run: cd ../ci-bun && bun --bun run build env: - NEXTAUTH_SECRET: foo + AUTH_SECRET: foo + AUTH_DISCORD_ID: bar + AUTH_DISCORD_SECRET: baz DATABASE_URL: mysql://root:root@localhost:3306/test # can't use url from example env cause we block that in t3-env - DISCORD_CLIENT_ID: bar - DISCORD_CLIENT_SECRET: baz diff --git a/cli/src/helpers/logNextSteps.ts b/cli/src/helpers/logNextSteps.ts index 88629fc1b4..9ba296b55d 100644 --- a/cli/src/helpers/logNextSteps.ts +++ b/cli/src/helpers/logNextSteps.ts @@ -47,6 +47,12 @@ export const logNextSteps = async ({ } } + if (packages?.nextAuth.inUse) { + logger.info( + ` Fill in your .env with necessary values. See https://create.t3.gg/en/usage/first-steps for more info.` + ); + } + if (["npm", "bun"].includes(pkgManager)) { logger.info(` ${pkgManager} run dev`); } else { diff --git a/cli/src/installers/dependencyVersionMap.ts b/cli/src/installers/dependencyVersionMap.ts index 062c9e3740..868214a665 100644 --- a/cli/src/installers/dependencyVersionMap.ts +++ b/cli/src/installers/dependencyVersionMap.ts @@ -4,9 +4,9 @@ */ export const dependencyVersionMap = { // NextAuth.js - "next-auth": "^4.24.7", - "@auth/prisma-adapter": "^1.6.0", - "@auth/drizzle-adapter": "^1.1.0", + "next-auth": "5.0.0-beta.25", + "@auth/prisma-adapter": "^2.7.2", + "@auth/drizzle-adapter": "^1.7.2", // Prisma prisma: "^5.14.0", diff --git a/cli/src/installers/envVars.ts b/cli/src/installers/envVars.ts index a7377ccf6e..6288fab1b5 100644 --- a/cli/src/installers/envVars.ts +++ b/cli/src/installers/envVars.ts @@ -51,8 +51,19 @@ export const envVariablesInstaller: Installer = ({ const envDest = path.join(projectDir, ".env"); const envExampleDest = path.join(projectDir, ".env.example"); - fs.writeFileSync(envDest, envContent, "utf-8"); - fs.writeFileSync(envExampleDest, exampleEnvContent + envContent, "utf-8"); + const _exampleEnvContent = exampleEnvContent + envContent; + + // Generate an auth secret and put in .env, not .env.example + const secret = Buffer.from( + crypto.getRandomValues(new Uint8Array(32)) + ).toString("base64"); + const _envContent = envContent.replace( + 'AUTH_SECRET=""', + `AUTH_SECRET="${secret}" # Generated by create-t3-app.` + ); + + fs.writeFileSync(envDest, _envContent, "utf-8"); + fs.writeFileSync(envExampleDest, _exampleEnvContent, "utf-8"); }; const getEnvContent = ( @@ -69,6 +80,19 @@ const getEnvContent = ( .trim() .concat("\n"); + if (usingAuth) + content += ` +# Next Auth +# You can generate a new secret on the command line with: +# npx auth secret +# https://next-auth.js.org/configuration/options#secret +AUTH_SECRET="" + +# Next Auth Discord Provider +AUTH_DISCORD_ID="" +AUTH_DISCORD_SECRET="" +`; + if (usingPrisma) content += ` # Prisma @@ -97,20 +121,6 @@ DATABASE_URL='mysql://YOUR_MYSQL_URL_HERE?sslaccept=strict'`; content += "\n"; } - if (usingAuth) - content += ` -# Next Auth -# You can generate a new secret on the command line with: -# openssl rand -base64 32 -# https://next-auth.js.org/configuration/options#secret -# NEXTAUTH_SECRET="" -NEXTAUTH_URL="http://localhost:3000" - -# Next Auth Discord Provider -DISCORD_CLIENT_ID="" -DISCORD_CLIENT_SECRET="" -`; - if (!usingAuth && !usingPrisma) content += ` # Example: diff --git a/cli/src/installers/nextAuth.ts b/cli/src/installers/nextAuth.ts index 0886e90d7e..242c8e619b 100644 --- a/cli/src/installers/nextAuth.ts +++ b/cli/src/installers/nextAuth.ts @@ -6,11 +6,7 @@ import { type AvailableDependencies } from "~/installers/dependencyVersionMap.js import { type Installer } from "~/installers/index.js"; import { addPackageDependency } from "~/utils/addPackageDependency.js"; -export const nextAuthInstaller: Installer = ({ - projectDir, - packages, - appRouter, -}) => { +export const nextAuthInstaller: Installer = ({ projectDir, packages }) => { const usingPrisma = packages?.prisma.inUse; const usingDrizzle = packages?.drizzle.inUse; @@ -26,25 +22,26 @@ export const nextAuthInstaller: Installer = ({ const extrasDir = path.join(PKG_ROOT, "template/extras"); - const apiHandlerFile = "src/pages/api/auth/[...nextauth].ts"; - const routeHandlerFile = "src/app/api/auth/[...nextauth]/route.ts"; - const srcToUse = appRouter ? routeHandlerFile : apiHandlerFile; + const apiHandlerFile = "src/app/api/auth/[...nextauth]/route.ts"; - const apiHandlerSrc = path.join(extrasDir, srcToUse); - const apiHandlerDest = path.join(projectDir, srcToUse); + const apiHandlerSrc = path.join(extrasDir, apiHandlerFile); + const apiHandlerDest = path.join(projectDir, apiHandlerFile); const authConfigSrc = path.join( extrasDir, - "src/server", - appRouter ? "auth-app" : "auth-pages", + "src/server/auth/config", usingPrisma ? "with-prisma.ts" : usingDrizzle ? "with-drizzle.ts" : "base.ts" ); - const authConfigDest = path.join(projectDir, "src/server/auth.ts"); + const authConfigDest = path.join(projectDir, "src/server/auth/config.ts"); + + const authIndexSrc = path.join(extrasDir, "src/server/auth/index.ts"); + const authIndexDest = path.join(projectDir, "src/server/auth/index.ts"); fs.copySync(apiHandlerSrc, apiHandlerDest); fs.copySync(authConfigSrc, authConfigDest); + fs.copySync(authIndexSrc, authIndexDest); }; diff --git a/cli/src/installers/tailwind.ts b/cli/src/installers/tailwind.ts index c50ab68dc7..86188a241d 100644 --- a/cli/src/installers/tailwind.ts +++ b/cli/src/installers/tailwind.ts @@ -23,8 +23,8 @@ export const tailwindInstaller: Installer = ({ projectDir }) => { const twCfgSrc = path.join(extrasDir, "config/tailwind.config.ts"); const twCfgDest = path.join(projectDir, "tailwind.config.ts"); - const postcssCfgSrc = path.join(extrasDir, "config/postcss.config.cjs"); - const postcssCfgDest = path.join(projectDir, "postcss.config.cjs"); + const postcssCfgSrc = path.join(extrasDir, "config/postcss.config.js"); + const postcssCfgDest = path.join(projectDir, "postcss.config.js"); const prettierSrc = path.join(extrasDir, "config/_prettier.config.js"); const prettierDest = path.join(projectDir, "prettier.config.js"); diff --git a/cli/template/base/next.config.js b/cli/template/base/next.config.js index 98b6f90a51..0eff695958 100644 --- a/cli/template/base/next.config.js +++ b/cli/template/base/next.config.js @@ -2,7 +2,7 @@ * Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially useful * for Docker builds. */ -await import("./src/env.js"); +import "./src/env.js"; /** @type {import("next").NextConfig} */ const config = { diff --git a/cli/template/base/package.json b/cli/template/base/package.json index fff75519f8..00ca211bdc 100644 --- a/cli/template/base/package.json +++ b/cli/template/base/package.json @@ -4,7 +4,7 @@ "type": "module", "private": true, "scripts": { - "dev": "next dev", + "dev": "next dev --turbo", "build": "next build", "start": "next start", "lint": "next lint", @@ -16,7 +16,7 @@ "dependencies": { "@t3-oss/env-nextjs": "^0.10.1", "geist": "^1.3.0", - "next": "^14.2.4", + "next": "^15.0.1", "react": "^18.3.1", "react-dom": "^18.3.1", "zod": "^3.23.3" @@ -29,7 +29,7 @@ "@typescript-eslint/eslint-plugin": "^8.1.0", "@typescript-eslint/parser": "^8.1.0", "eslint": "^8.57.0", - "eslint-config-next": "^14.2.4", + "eslint-config-next": "^15.0.1", "typescript": "^5.5.3" } } diff --git a/cli/template/extras/config/_prettier.config.js b/cli/template/extras/config/_prettier.config.js index b2d59b460f..da332bd898 100644 --- a/cli/template/extras/config/_prettier.config.js +++ b/cli/template/extras/config/_prettier.config.js @@ -1,6 +1,4 @@ /** @type {import('prettier').Config & import('prettier-plugin-tailwindcss').PluginOptions} */ -const config = { +export default { plugins: ["prettier-plugin-tailwindcss"], }; - -export default config; diff --git a/cli/template/extras/config/next-config-appdir.js b/cli/template/extras/config/next-config-appdir.js index 9bfe4a0e2a..121c4f4c24 100644 --- a/cli/template/extras/config/next-config-appdir.js +++ b/cli/template/extras/config/next-config-appdir.js @@ -2,7 +2,7 @@ * Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially useful * for Docker builds. */ -await import("./src/env.js"); +import "./src/env.js"; /** @type {import("next").NextConfig} */ const config = {}; diff --git a/cli/template/extras/config/postcss.config.cjs b/cli/template/extras/config/postcss.config.cjs deleted file mode 100644 index 4cdb2f430f..0000000000 --- a/cli/template/extras/config/postcss.config.cjs +++ /dev/null @@ -1,7 +0,0 @@ -const config = { - plugins: { - tailwindcss: {}, - }, -}; - -module.exports = config; diff --git a/cli/template/extras/config/postcss.config.js b/cli/template/extras/config/postcss.config.js new file mode 100644 index 0000000000..01bf7432f6 --- /dev/null +++ b/cli/template/extras/config/postcss.config.js @@ -0,0 +1,5 @@ +export default { + plugins: { + tailwindcss: {}, + }, +}; diff --git a/cli/template/extras/src/app/api/auth/[...nextauth]/route.ts b/cli/template/extras/src/app/api/auth/[...nextauth]/route.ts index 7ef89677f2..8e8302c8d8 100644 --- a/cli/template/extras/src/app/api/auth/[...nextauth]/route.ts +++ b/cli/template/extras/src/app/api/auth/[...nextauth]/route.ts @@ -1,7 +1,3 @@ -import NextAuth from "next-auth"; +import { handlers } from "~/server/auth"; -import { authOptions } from "~/server/auth"; - -// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -const handler = NextAuth(authOptions); -export { handler as GET, handler as POST }; +export const { GET, POST } = handlers; diff --git a/cli/template/extras/src/app/page/with-auth-trpc-tw.tsx b/cli/template/extras/src/app/page/with-auth-trpc-tw.tsx index 1d462b4441..37cc32ff48 100644 --- a/cli/template/extras/src/app/page/with-auth-trpc-tw.tsx +++ b/cli/template/extras/src/app/page/with-auth-trpc-tw.tsx @@ -1,12 +1,12 @@ import Link from "next/link"; import { LatestPost } from "~/app/_components/post"; -import { getServerAuthSession } from "~/server/auth"; +import { auth } from "~/server/auth"; import { api, HydrateClient } from "~/trpc/server"; export default async function Home() { const hello = await api.post.hello({ text: "from tRPC" }); - const session = await getServerAuthSession(); + const session = await auth(); if (session?.user) { void api.post.getLatest.prefetch(); diff --git a/cli/template/extras/src/app/page/with-auth-trpc.tsx b/cli/template/extras/src/app/page/with-auth-trpc.tsx index 74cac168f9..ba570d252e 100644 --- a/cli/template/extras/src/app/page/with-auth-trpc.tsx +++ b/cli/template/extras/src/app/page/with-auth-trpc.tsx @@ -1,13 +1,13 @@ import Link from "next/link"; import { LatestPost } from "~/app/_components/post"; -import { getServerAuthSession } from "~/server/auth"; +import { auth } from "~/server/auth"; import { api, HydrateClient } from "~/trpc/server"; import styles from "./index.module.css"; export default async function Home() { const hello = await api.post.hello({ text: "from tRPC" }); - const session = await getServerAuthSession(); + const session = await auth(); if (session?.user) { void api.post.getLatest.prefetch(); diff --git a/cli/template/extras/src/env/with-auth-db-planetscale.js b/cli/template/extras/src/env/with-auth-db-planetscale.js index 35a053ec5b..01abd8e6f1 100644 --- a/cli/template/extras/src/env/with-auth-db-planetscale.js +++ b/cli/template/extras/src/env/with-auth-db-planetscale.js @@ -7,6 +7,12 @@ export const env = createEnv({ * isn't built with invalid env vars. */ server: { + AUTH_SECRET: + process.env.NODE_ENV === "production" + ? z.string() + : z.string().optional(), + AUTH_DISCORD_ID: z.string(), + AUTH_DISCORD_SECRET: z.string(), DATABASE_URL: z .string() .url() @@ -17,19 +23,6 @@ export const env = createEnv({ NODE_ENV: z .enum(["development", "test", "production"]) .default("development"), - NEXTAUTH_SECRET: - process.env.NODE_ENV === "production" - ? z.string() - : z.string().optional(), - NEXTAUTH_URL: z.preprocess( - // This makes Vercel deployments not fail if you don't set NEXTAUTH_URL - // Since NextAuth.js automatically uses the VERCEL_URL if present. - (str) => process.env.VERCEL_URL ?? str, - // VERCEL_URL doesn't include `https` so it cant be validated as a URL - process.env.VERCEL ? z.string() : z.string().url() - ), - DISCORD_CLIENT_ID: z.string(), - DISCORD_CLIENT_SECRET: z.string(), }, /** @@ -46,12 +39,11 @@ export const env = createEnv({ * middlewares) or client-side so we need to destruct manually. */ runtimeEnv: { + AUTH_SECRET: process.env.AUTH_SECRET, + AUTH_DISCORD_ID: process.env.AUTH_DISCORD_ID, + AUTH_DISCORD_SECRET: process.env.AUTH_DISCORD_SECRET, DATABASE_URL: process.env.DATABASE_URL, NODE_ENV: process.env.NODE_ENV, - NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET, - NEXTAUTH_URL: process.env.NEXTAUTH_URL, - DISCORD_CLIENT_ID: process.env.DISCORD_CLIENT_ID, - DISCORD_CLIENT_SECRET: process.env.DISCORD_CLIENT_SECRET, }, /** * Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially diff --git a/cli/template/extras/src/env/with-auth-db.js b/cli/template/extras/src/env/with-auth-db.js index 2467d22d0f..6b19f72401 100644 --- a/cli/template/extras/src/env/with-auth-db.js +++ b/cli/template/extras/src/env/with-auth-db.js @@ -7,23 +7,16 @@ export const env = createEnv({ * isn't built with invalid env vars. */ server: { + AUTH_SECRET: + process.env.NODE_ENV === "production" + ? z.string() + : z.string().optional(), + AUTH_DISCORD_ID: z.string(), + AUTH_DISCORD_SECRET: z.string(), DATABASE_URL: z.string().url(), NODE_ENV: z .enum(["development", "test", "production"]) .default("development"), - NEXTAUTH_SECRET: - process.env.NODE_ENV === "production" - ? z.string() - : z.string().optional(), - NEXTAUTH_URL: z.preprocess( - // This makes Vercel deployments not fail if you don't set NEXTAUTH_URL - // Since NextAuth.js automatically uses the VERCEL_URL if present. - (str) => process.env.VERCEL_URL ?? str, - // VERCEL_URL doesn't include `https` so it cant be validated as a URL - process.env.VERCEL ? z.string() : z.string().url() - ), - DISCORD_CLIENT_ID: z.string(), - DISCORD_CLIENT_SECRET: z.string(), }, /** @@ -40,12 +33,11 @@ export const env = createEnv({ * middlewares) or client-side so we need to destruct manually. */ runtimeEnv: { + AUTH_SECRET: process.env.AUTH_SECRET, + AUTH_DISCORD_ID: process.env.AUTH_DISCORD_ID, + AUTH_DISCORD_SECRET: process.env.AUTH_DISCORD_SECRET, DATABASE_URL: process.env.DATABASE_URL, NODE_ENV: process.env.NODE_ENV, - NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET, - NEXTAUTH_URL: process.env.NEXTAUTH_URL, - DISCORD_CLIENT_ID: process.env.DISCORD_CLIENT_ID, - DISCORD_CLIENT_SECRET: process.env.DISCORD_CLIENT_SECRET, }, /** * Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially diff --git a/cli/template/extras/src/env/with-auth.js b/cli/template/extras/src/env/with-auth.js index 42cc12648d..45b5cba0a3 100644 --- a/cli/template/extras/src/env/with-auth.js +++ b/cli/template/extras/src/env/with-auth.js @@ -7,22 +7,15 @@ export const env = createEnv({ * isn't built with invalid env vars. */ server: { - NODE_ENV: z - .enum(["development", "test", "production"]) - .default("development"), - NEXTAUTH_SECRET: + AUTH_SECRET: process.env.NODE_ENV === "production" ? z.string() : z.string().optional(), - NEXTAUTH_URL: z.preprocess( - // This makes Vercel deployments not fail if you don't set NEXTAUTH_URL - // Since NextAuth.js automatically uses the VERCEL_URL if present. - (str) => process.env.VERCEL_URL ?? str, - // VERCEL_URL doesn't include `https` so it cant be validated as a URL - process.env.VERCEL ? z.string() : z.string().url() - ), - DISCORD_CLIENT_ID: z.string(), - DISCORD_CLIENT_SECRET: z.string(), + AUTH_DISCORD_ID: z.string(), + AUTH_DISCORD_SECRET: z.string(), + NODE_ENV: z + .enum(["development", "test", "production"]) + .default("development"), }, /** @@ -39,11 +32,10 @@ export const env = createEnv({ * middlewares) or client-side so we need to destruct manually. */ runtimeEnv: { + AUTH_SECRET: process.env.AUTH_SECRET, + AUTH_DISCORD_ID: process.env.AUTH_DISCORD_ID, + AUTH_DISCORD_SECRET: process.env.AUTH_DISCORD_SECRET, NODE_ENV: process.env.NODE_ENV, - NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET, - NEXTAUTH_URL: process.env.NEXTAUTH_URL, - DISCORD_CLIENT_ID: process.env.DISCORD_CLIENT_ID, - DISCORD_CLIENT_SECRET: process.env.DISCORD_CLIENT_SECRET, // NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR, }, /** diff --git a/cli/template/extras/src/pages/api/auth/[...nextauth].ts b/cli/template/extras/src/pages/api/auth/[...nextauth].ts deleted file mode 100644 index 8739530ffd..0000000000 --- a/cli/template/extras/src/pages/api/auth/[...nextauth].ts +++ /dev/null @@ -1,5 +0,0 @@ -import NextAuth from "next-auth"; - -import { authOptions } from "~/server/auth"; - -export default NextAuth(authOptions); diff --git a/cli/template/extras/src/server/api/trpc-app/with-auth-db.ts b/cli/template/extras/src/server/api/trpc-app/with-auth-db.ts index 0021e07cbd..00d924faa8 100644 --- a/cli/template/extras/src/server/api/trpc-app/with-auth-db.ts +++ b/cli/template/extras/src/server/api/trpc-app/with-auth-db.ts @@ -11,7 +11,7 @@ import { initTRPC, TRPCError } from "@trpc/server"; import superjson from "superjson"; import { ZodError } from "zod"; -import { getServerAuthSession } from "~/server/auth"; +import { auth } from "~/server/auth"; import { db } from "~/server/db"; /** @@ -27,7 +27,7 @@ import { db } from "~/server/db"; * @see https://trpc.io/docs/server/context */ export const createTRPCContext = async (opts: { headers: Headers }) => { - const session = await getServerAuthSession(); + const session = await auth(); return { db, diff --git a/cli/template/extras/src/server/api/trpc-app/with-auth.ts b/cli/template/extras/src/server/api/trpc-app/with-auth.ts index 3c688d34c2..755b973c29 100644 --- a/cli/template/extras/src/server/api/trpc-app/with-auth.ts +++ b/cli/template/extras/src/server/api/trpc-app/with-auth.ts @@ -10,7 +10,7 @@ import { initTRPC, TRPCError } from "@trpc/server"; import superjson from "superjson"; import { ZodError } from "zod"; -import { getServerAuthSession } from "~/server/auth"; +import { auth } from "~/server/auth"; /** * 1. CONTEXT @@ -25,7 +25,7 @@ import { getServerAuthSession } from "~/server/auth"; * @see https://trpc.io/docs/server/context */ export const createTRPCContext = async (opts: { headers: Headers }) => { - const session = await getServerAuthSession(); + const session = await auth(); return { session, diff --git a/cli/template/extras/src/server/api/trpc-pages/with-auth-db.ts b/cli/template/extras/src/server/api/trpc-pages/with-auth-db.ts index b0456c8f94..8b4f3632a7 100644 --- a/cli/template/extras/src/server/api/trpc-pages/with-auth-db.ts +++ b/cli/template/extras/src/server/api/trpc-pages/with-auth-db.ts @@ -13,7 +13,7 @@ import { type Session } from "next-auth"; import superjson from "superjson"; import { ZodError } from "zod"; -import { getServerAuthSession } from "~/server/auth"; +import { auth } from "~/server/auth"; import { db } from "~/server/db"; /** @@ -55,7 +55,7 @@ export const createTRPCContext = async (opts: CreateNextContextOptions) => { const { req, res } = opts; // Get the session from the server using the getServerSession wrapper function - const session = await getServerAuthSession({ req, res }); + const session = await auth(req, res); return createInnerTRPCContext({ session, diff --git a/cli/template/extras/src/server/api/trpc-pages/with-auth.ts b/cli/template/extras/src/server/api/trpc-pages/with-auth.ts index 3148e056f1..7fe732be6b 100644 --- a/cli/template/extras/src/server/api/trpc-pages/with-auth.ts +++ b/cli/template/extras/src/server/api/trpc-pages/with-auth.ts @@ -12,7 +12,7 @@ import { type Session } from "next-auth"; import superjson from "superjson"; import { ZodError } from "zod"; -import { getServerAuthSession } from "~/server/auth"; +import { auth } from "~/server/auth"; /** * 1. CONTEXT @@ -53,7 +53,7 @@ export const createTRPCContext = async ({ res, }: CreateNextContextOptions) => { // Get the session from the server using the getServerSession wrapper function - const session = await getServerAuthSession({ req, res }); + const session = await auth(req, res); return createInnerTRPCContext({ session, diff --git a/cli/template/extras/src/server/auth-pages/base.ts b/cli/template/extras/src/server/auth-pages/base.ts deleted file mode 100644 index cbeceb4c16..0000000000 --- a/cli/template/extras/src/server/auth-pages/base.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { type GetServerSidePropsContext } from "next"; -import { - getServerSession, - type DefaultSession, - type NextAuthOptions, -} from "next-auth"; -import DiscordProvider from "next-auth/providers/discord"; - -import { env } from "~/env"; - -/** - * Module augmentation for `next-auth` types. Allows us to add custom properties to the `session` - * object and keep type safety. - * - * @see https://next-auth.js.org/getting-started/typescript#module-augmentation - */ -declare module "next-auth" { - interface Session extends DefaultSession { - user: DefaultSession["user"] & { - id: string; - // ...other properties - // role: UserRole; - }; - } - - // interface User { - // // ...other properties - // // role: UserRole; - // } -} - -/** - * Options for NextAuth.js used to configure adapters, providers, callbacks, etc. - * - * @see https://next-auth.js.org/configuration/options - */ -export const authOptions: NextAuthOptions = { - callbacks: { - session: ({ session, token }) => ({ - ...session, - user: { - ...session.user, - id: token.sub, - }, - }), - }, - providers: [ - DiscordProvider({ - clientId: env.DISCORD_CLIENT_ID, - clientSecret: env.DISCORD_CLIENT_SECRET, - }), - /** - * ...add more providers here. - * - * Most other providers require a bit more work than the Discord provider. For example, the - * GitHub provider requires you to add the `refresh_token_expires_in` field to the Account - * model. Refer to the NextAuth.js docs for the provider you want to use. Example: - * - * @see https://next-auth.js.org/providers/github - */ - ], -}; - -/** - * Wrapper for `getServerSession` so that you don't need to import the `authOptions` in every file. - * - * @see https://next-auth.js.org/configuration/nextjs - */ -export const getServerAuthSession = (ctx: { - req: GetServerSidePropsContext["req"]; - res: GetServerSidePropsContext["res"]; -}) => { - return getServerSession(ctx.req, ctx.res, authOptions); -}; diff --git a/cli/template/extras/src/server/auth-pages/with-drizzle.ts b/cli/template/extras/src/server/auth-pages/with-drizzle.ts deleted file mode 100644 index c7788937f0..0000000000 --- a/cli/template/extras/src/server/auth-pages/with-drizzle.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { DrizzleAdapter } from "@auth/drizzle-adapter"; -import { type GetServerSidePropsContext } from "next"; -import { - getServerSession, - type DefaultSession, - type NextAuthOptions, -} from "next-auth"; -import { type Adapter } from "next-auth/adapters"; -import DiscordProvider from "next-auth/providers/discord"; - -import { env } from "~/env"; -import { db } from "~/server/db"; -import { - accounts, - sessions, - users, - verificationTokens, -} from "~/server/db/schema"; - -/** - * Module augmentation for `next-auth` types. Allows us to add custom properties to the `session` - * object and keep type safety. - * - * @see https://next-auth.js.org/getting-started/typescript#module-augmentation - */ -declare module "next-auth" { - interface Session extends DefaultSession { - user: { - id: string; - // ...other properties - // role: UserRole; - } & DefaultSession["user"]; - } - - // interface User { - // // ...other properties - // // role: UserRole; - // } -} - -/** - * Options for NextAuth.js used to configure adapters, providers, callbacks, etc. - * - * @see https://next-auth.js.org/configuration/options - */ -export const authOptions: NextAuthOptions = { - callbacks: { - session: ({ session, user }) => ({ - ...session, - user: { - ...session.user, - id: user.id, - }, - }), - }, - adapter: DrizzleAdapter(db, { - usersTable: users, - accountsTable: accounts, - sessionsTable: sessions, - verificationTokensTable: verificationTokens, - }) as Adapter, - providers: [ - DiscordProvider({ - clientId: env.DISCORD_CLIENT_ID, - clientSecret: env.DISCORD_CLIENT_SECRET, - }), - /** - * ...add more providers here. - * - * Most other providers require a bit more work than the Discord provider. For example, the - * GitHub provider requires you to add the `refresh_token_expires_in` field to the Account - * model. Refer to the NextAuth.js docs for the provider you want to use. Example: - * - * @see https://next-auth.js.org/providers/github - */ - ], -}; - -/** - * Wrapper for `getServerSession` so that you don't need to import the `authOptions` in every file. - * - * @see https://next-auth.js.org/configuration/nextjs - */ -export const getServerAuthSession = (ctx: { - req: GetServerSidePropsContext["req"]; - res: GetServerSidePropsContext["res"]; -}) => { - return getServerSession(ctx.req, ctx.res, authOptions); -}; diff --git a/cli/template/extras/src/server/auth-pages/with-prisma.ts b/cli/template/extras/src/server/auth-pages/with-prisma.ts deleted file mode 100644 index ee03a40d73..0000000000 --- a/cli/template/extras/src/server/auth-pages/with-prisma.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { PrismaAdapter } from "@auth/prisma-adapter"; -import { type GetServerSidePropsContext } from "next"; -import { - getServerSession, - type DefaultSession, - type NextAuthOptions, -} from "next-auth"; -import { type Adapter } from "next-auth/adapters"; -import DiscordProvider from "next-auth/providers/discord"; - -import { env } from "~/env"; -import { db } from "~/server/db"; - -/** - * Module augmentation for `next-auth` types. Allows us to add custom properties to the `session` - * object and keep type safety. - * - * @see https://next-auth.js.org/getting-started/typescript#module-augmentation - */ -declare module "next-auth" { - interface Session extends DefaultSession { - user: DefaultSession["user"] & { - id: string; - // ...other properties - // role: UserRole; - }; - } - - // interface User { - // // ...other properties - // // role: UserRole; - // } -} - -/** - * Options for NextAuth.js used to configure adapters, providers, callbacks, etc. - * - * @see https://next-auth.js.org/configuration/options - */ -export const authOptions: NextAuthOptions = { - callbacks: { - session: ({ session, user }) => ({ - ...session, - user: { - ...session.user, - id: user.id, - }, - }), - }, - adapter: PrismaAdapter(db) as Adapter, - providers: [ - DiscordProvider({ - clientId: env.DISCORD_CLIENT_ID, - clientSecret: env.DISCORD_CLIENT_SECRET, - }), - /** - * ...add more providers here. - * - * Most other providers require a bit more work than the Discord provider. For example, the - * GitHub provider requires you to add the `refresh_token_expires_in` field to the Account - * model. Refer to the NextAuth.js docs for the provider you want to use. Example: - * - * @see https://next-auth.js.org/providers/github - */ - ], -}; - -/** - * Wrapper for `getServerSession` so that you don't need to import the `authOptions` in every file. - * - * @see https://next-auth.js.org/configuration/nextjs - */ -export const getServerAuthSession = (ctx: { - req: GetServerSidePropsContext["req"]; - res: GetServerSidePropsContext["res"]; -}) => { - return getServerSession(ctx.req, ctx.res, authOptions); -}; diff --git a/cli/template/extras/src/server/auth-app/base.ts b/cli/template/extras/src/server/auth/config/base.ts similarity index 70% rename from cli/template/extras/src/server/auth-app/base.ts rename to cli/template/extras/src/server/auth/config/base.ts index 9c170aaaae..c88101a0b4 100644 --- a/cli/template/extras/src/server/auth-app/base.ts +++ b/cli/template/extras/src/server/auth/config/base.ts @@ -1,12 +1,6 @@ -import { - getServerSession, - type DefaultSession, - type NextAuthOptions, -} from "next-auth"; +import { type DefaultSession, type NextAuthConfig } from "next-auth"; import DiscordProvider from "next-auth/providers/discord"; -import { env } from "~/env"; - /** * Module augmentation for `next-auth` types. Allows us to add custom properties to the `session` * object and keep type safety. @@ -33,21 +27,9 @@ declare module "next-auth" { * * @see https://next-auth.js.org/configuration/options */ -export const authOptions: NextAuthOptions = { - callbacks: { - session: ({ session, token }) => ({ - ...session, - user: { - ...session.user, - id: token.sub, - }, - }), - }, +export const authConfig = { providers: [ - DiscordProvider({ - clientId: env.DISCORD_CLIENT_ID, - clientSecret: env.DISCORD_CLIENT_SECRET, - }), + DiscordProvider, /** * ...add more providers here. * @@ -58,11 +40,13 @@ export const authOptions: NextAuthOptions = { * @see https://next-auth.js.org/providers/github */ ], -}; - -/** - * Wrapper for `getServerSession` so that you don't need to import the `authOptions` in every file. - * - * @see https://next-auth.js.org/configuration/nextjs - */ -export const getServerAuthSession = () => getServerSession(authOptions); + callbacks: { + session: ({ session, token }) => ({ + ...session, + user: { + ...session.user, + id: token.sub, + }, + }), + }, +} satisfies NextAuthConfig; diff --git a/cli/template/extras/src/server/auth-app/with-drizzle.ts b/cli/template/extras/src/server/auth/config/with-drizzle.ts similarity index 73% rename from cli/template/extras/src/server/auth-app/with-drizzle.ts rename to cli/template/extras/src/server/auth/config/with-drizzle.ts index 6e9281d157..3ef82a2f63 100644 --- a/cli/template/extras/src/server/auth-app/with-drizzle.ts +++ b/cli/template/extras/src/server/auth/config/with-drizzle.ts @@ -1,13 +1,7 @@ import { DrizzleAdapter } from "@auth/drizzle-adapter"; -import { - getServerSession, - type DefaultSession, - type NextAuthOptions, -} from "next-auth"; -import { type Adapter } from "next-auth/adapters"; +import { type DefaultSession, type NextAuthConfig } from "next-auth"; import DiscordProvider from "next-auth/providers/discord"; -import { env } from "~/env"; import { db } from "~/server/db"; import { accounts, @@ -42,27 +36,9 @@ declare module "next-auth" { * * @see https://next-auth.js.org/configuration/options */ -export const authOptions: NextAuthOptions = { - callbacks: { - session: ({ session, user }) => ({ - ...session, - user: { - ...session.user, - id: user.id, - }, - }), - }, - adapter: DrizzleAdapter(db, { - usersTable: users, - accountsTable: accounts, - sessionsTable: sessions, - verificationTokensTable: verificationTokens, - }) as Adapter, +export const authConfig = { providers: [ - DiscordProvider({ - clientId: env.DISCORD_CLIENT_ID, - clientSecret: env.DISCORD_CLIENT_SECRET, - }), + DiscordProvider, /** * ...add more providers here. * @@ -73,11 +49,19 @@ export const authOptions: NextAuthOptions = { * @see https://next-auth.js.org/providers/github */ ], -}; - -/** - * Wrapper for `getServerSession` so that you don't need to import the `authOptions` in every file. - * - * @see https://next-auth.js.org/configuration/nextjs - */ -export const getServerAuthSession = () => getServerSession(authOptions); + adapter: DrizzleAdapter(db, { + usersTable: users, + accountsTable: accounts, + sessionsTable: sessions, + verificationTokensTable: verificationTokens, + }), + callbacks: { + session: ({ session, user }) => ({ + ...session, + user: { + ...session.user, + id: user.id, + }, + }), + }, +} satisfies NextAuthConfig; diff --git a/cli/template/extras/src/server/auth-app/with-prisma.ts b/cli/template/extras/src/server/auth/config/with-prisma.ts similarity index 68% rename from cli/template/extras/src/server/auth-app/with-prisma.ts rename to cli/template/extras/src/server/auth/config/with-prisma.ts index 117984c9bd..9b8ec7997f 100644 --- a/cli/template/extras/src/server/auth-app/with-prisma.ts +++ b/cli/template/extras/src/server/auth/config/with-prisma.ts @@ -1,13 +1,7 @@ import { PrismaAdapter } from "@auth/prisma-adapter"; -import { - getServerSession, - type DefaultSession, - type NextAuthOptions, -} from "next-auth"; -import { type Adapter } from "next-auth/adapters"; +import { type DefaultSession, type NextAuthConfig } from "next-auth"; import DiscordProvider from "next-auth/providers/discord"; -import { env } from "~/env"; import { db } from "~/server/db"; /** @@ -36,22 +30,9 @@ declare module "next-auth" { * * @see https://next-auth.js.org/configuration/options */ -export const authOptions: NextAuthOptions = { - callbacks: { - session: ({ session, user }) => ({ - ...session, - user: { - ...session.user, - id: user.id, - }, - }), - }, - adapter: PrismaAdapter(db) as Adapter, +export const authConfig = { providers: [ - DiscordProvider({ - clientId: env.DISCORD_CLIENT_ID, - clientSecret: env.DISCORD_CLIENT_SECRET, - }), + DiscordProvider, /** * ...add more providers here. * @@ -62,11 +43,14 @@ export const authOptions: NextAuthOptions = { * @see https://next-auth.js.org/providers/github */ ], -}; - -/** - * Wrapper for `getServerSession` so that you don't need to import the `authOptions` in every file. - * - * @see https://next-auth.js.org/configuration/nextjs - */ -export const getServerAuthSession = () => getServerSession(authOptions); + adapter: PrismaAdapter(db), + callbacks: { + session: ({ session, user }) => ({ + ...session, + user: { + ...session.user, + id: user.id, + }, + }), + }, +} satisfies NextAuthConfig; diff --git a/cli/template/extras/src/server/auth/index.ts b/cli/template/extras/src/server/auth/index.ts new file mode 100644 index 0000000000..76c146d34a --- /dev/null +++ b/cli/template/extras/src/server/auth/index.ts @@ -0,0 +1,10 @@ +import NextAuth from "next-auth"; +import { cache } from "react"; + +import { authConfig } from "./config"; + +const { auth: uncachedAuth, handlers, signIn, signOut } = NextAuth(authConfig); + +const auth = cache(uncachedAuth); + +export { auth, handlers, signIn, signOut }; diff --git a/cli/template/extras/src/trpc/server.ts b/cli/template/extras/src/trpc/server.ts index 59300a638b..91e557e45f 100644 --- a/cli/template/extras/src/trpc/server.ts +++ b/cli/template/extras/src/trpc/server.ts @@ -12,8 +12,8 @@ import { createQueryClient } from "./query-client"; * This wraps the `createTRPCContext` helper and provides the required context for the tRPC API when * handling a tRPC call from a React Server Component. */ -const createContext = cache(() => { - const heads = new Headers(headers()); +const createContext = cache(async () => { + const heads = new Headers(await headers()); heads.set("x-trpc-source", "rsc"); return createTRPCContext({ diff --git a/www/src/components/docs/folderStructureDiagramApp.astro b/www/src/components/docs/folderStructureDiagramApp.astro index 0b175db152..68e9690737 100644 --- a/www/src/components/docs/folderStructureDiagramApp.astro +++ b/www/src/components/docs/folderStructureDiagramApp.astro @@ -41,7 +41,7 @@ "next-env.d.ts": [], "next.config.js": [], "package.json": [], - "postcss.config.cjs": ["tailwind"], + "postcss.config.js": ["tailwind"], "prettier.config.js": ["tailwind"], "README.md": [], "start-database.sh (mysql or postgres only)": ["drizzle"], diff --git a/www/src/components/docs/folderStructureDiagramPages.astro b/www/src/components/docs/folderStructureDiagramPages.astro index 8676e66019..8756fb6f4c 100644 --- a/www/src/components/docs/folderStructureDiagramPages.astro +++ b/www/src/components/docs/folderStructureDiagramPages.astro @@ -38,7 +38,7 @@ "next-env.d.ts": [], "next.config.js": [], "package.json": [], - "postcss.config.cjs": ["tailwind"], + "postcss.config.js": ["tailwind"], "prettier.config.js": ["tailwind"], "README.md": [], "start-database.sh (mysql or postgres only)": ["drizzle"], diff --git a/www/src/components/navigation/tableOfContents.astro b/www/src/components/navigation/tableOfContents.astro index 65b9ad134f..fed095ffe8 100644 --- a/www/src/components/navigation/tableOfContents.astro +++ b/www/src/components/navigation/tableOfContents.astro @@ -39,7 +39,7 @@ const isRtl = getIsRtlFromUrl(pathname); case "src/server/auth.ts": dataComponentType = "nextauth"; break; - case "postcss.config.cjs": + case "postcss.config.js": case "prettier.config.mjs": dataComponentType = "tailwind"; break; diff --git a/www/src/pages/ar/folder-structure-pages.mdx b/www/src/pages/ar/folder-structure-pages.mdx index aafcc4f850..95ddbefc07 100644 --- a/www/src/pages/ar/folder-structure-pages.mdx +++ b/www/src/pages/ar/folder-structure-pages.mdx @@ -198,9 +198,9 @@ import Form from "../../components/docs/folderStructureForm.astro";
http://localhost:3000/api/auth/callback/discord
)
- Save your changes
- It is possible, but not recommended, to use the same Discord Application for both development and production. You could also consider [Mocking the Provider](https://github.com/trpc/trpc/blob/main/examples/next-prisma-websockets-starter/src/pages/api/auth/%5B...nextauth%5D.ts) during development.
diff --git a/www/src/pages/es/folder-structure-pages.mdx b/www/src/pages/es/folder-structure-pages.mdx
index 53f5298121..38017f3cc3 100644
--- a/www/src/pages/es/folder-structure-pages.mdx
+++ b/www/src/pages/es/folder-structure-pages.mdx
@@ -206,9 +206,9 @@ El archivo `next.config.mjs` se usa para configurar Next.js. Consulta [la docume
http://localhost:3000/api/auth/callback/discord
)
- Guarda tus cambios
- Es posible, pero no recomendado, usar la misma aplicación de Discord tanto para desarrollo como para producción. También puedes considerar hacer un [mock del proveedor](https://github.com/trpc/trpc/blob/main/examples/next-prisma-websockets-starter/src/pages/api/auth/%5B...nextauth%5D.ts) durante el desarrollo.
diff --git a/www/src/pages/fr/folder-structure-pages.mdx b/www/src/pages/fr/folder-structure-pages.mdx
index cd85a7e057..bf54572dd2 100644
--- a/www/src/pages/fr/folder-structure-pages.mdx
+++ b/www/src/pages/fr/folder-structure-pages.mdx
@@ -197,9 +197,9 @@ Le fichier `next.config.mjs` est utilisé pour configurer Next.js. Voir la [docu
http://localhost:3000/api/auth/rappel/discord
)
- Enregistrez vos modifications
diff --git a/www/src/pages/ja/folder-structure-pages.mdx b/www/src/pages/ja/folder-structure-pages.mdx
index 649ad650f7..57482b1024 100644
--- a/www/src/pages/ja/folder-structure-pages.mdx
+++ b/www/src/pages/ja/folder-structure-pages.mdx
@@ -187,9 +187,9 @@ import Form from "../../components/docs/folderStructureForm.astro";
http://localhost:3000/api/auth/callback/discord
)
- 変更を保存します
- 開発用と本番用で同じ Discord Application を使用できますが、推奨はしません。また、開発時には[プロバイダをモックする](https://github.com/trpc/trpc/blob/main/examples/next-prisma-websockets-starter/src/pages/api/auth/%5B...nextauth%5D.ts)こと検討するのもよいでしょう。
diff --git a/www/src/pages/no/folder-structure-pages.mdx b/www/src/pages/no/folder-structure-pages.mdx
index 5d08f774cf..b77fd3820c 100644
--- a/www/src/pages/no/folder-structure-pages.mdx
+++ b/www/src/pages/no/folder-structure-pages.mdx
@@ -183,9 +183,9 @@ Basert på dine valgte pakker inneholder denne ruteren flere eller færre ruter
http://localhost:3000/api/auth/callback/discord
)
- Lagre endringene dine
- Det er mulig, men ikke anbefalt, å bruke samme Discord-applikasjon for utvikling og produksjon. Du kan også vurdere å [Mocke leverandøren](https://github.com/trpc/trpc/blob/main/examples/next-prisma-websockets-starter/src/pages/api/auth/%5B...nextauth%5D.ts) under utviklingen.
diff --git a/www/src/pages/pl/folder-structure-pages.mdx b/www/src/pages/pl/folder-structure-pages.mdx
index 1a57fcdf80..0d935b79c6 100644
--- a/www/src/pages/pl/folder-structure-pages.mdx
+++ b/www/src/pages/pl/folder-structure-pages.mdx
@@ -184,9 +184,9 @@ Plik `next.config.mjs` jest używany do konfigurowania Next.js. Po więcej infor
http://localhost:3000/api/auth/callback/discord
)
- Zapisz zmiany
- Jest możliwość (nie jest ona jednak polecana), aby wykorzystać tą samą aplikację Discorda dla zarówno aplikacji lokalnej i tej w wersji produkcyjnej. Możesz także wykorzystać [mockowanie providera](https://github.com/trpc/trpc/blob/next/examples/next-prisma-starter-websockets/src/pages/api/auth/%5B...nextauth%5D.ts) podczas rozwoju aplikacji.
diff --git a/www/src/pages/pt/folder-structure-pages.mdx b/www/src/pages/pt/folder-structure-pages.mdx
index f88fdd5fe7..0dad871dfe 100644
--- a/www/src/pages/pt/folder-structure-pages.mdx
+++ b/www/src/pages/pt/folder-structure-pages.mdx
@@ -198,9 +198,9 @@ O arquivo `next.config.mjs` é usado para configura o Next.js. Veja [Documentaç
http://localhost:3000/api/auth/callback/discord
)
- Salve suas alterações
- É possível, mas não recomendado, usar o mesmo aplicativo Discord tanto para desenvolvimento quanto para produção. Você também pode considerar [mockar o Provider](https://github.com/trpc/trpc/blob/next/examples/next-prisma-starter-websockets/src/pages/api/auth/%5B...nextauth%5D.ts) durante o desenvolvimento.
diff --git a/www/src/pages/ru/folder-structure-pages.mdx b/www/src/pages/ru/folder-structure-pages.mdx
index 16e12e3b47..4ecfa05442 100644
--- a/www/src/pages/ru/folder-structure-pages.mdx
+++ b/www/src/pages/ru/folder-structure-pages.mdx
@@ -198,9 +198,9 @@ import Form from "../../components/docs/folderStructureForm.astro";
http://localhost:3000/api/auth/callback/discord
)
- Сохраните изменения
- Возможно, но не рекомендуется, использовать одно и то же приложение Discord для разработки и продакшена. Вы также можете рассмотреть [Mocking the Provider](https://github.com/trpc/trpc/blob/next/examples/next-prisma-starter-websockets/src/pages/api/auth/%5B...nextauth%5D.ts) во время разработки.
diff --git a/www/src/pages/uk/folder-structure-pages.mdx b/www/src/pages/uk/folder-structure-pages.mdx
index 9fdbedf015..bb1662d4bf 100644
--- a/www/src/pages/uk/folder-structure-pages.mdx
+++ b/www/src/pages/uk/folder-structure-pages.mdx
@@ -198,9 +198,9 @@ import Form from "../../components/docs/folderStructureForm.astro";
http://localhost:3000/api/auth/callback/discord
)
- Збережіть зміни
- Можливо, але не рекомендується, використовувати один і той же додаток Discord для розробки та продакшену. Ви також можете розглянути [Mocking the Provider](https://github.com/trpc/trpc/blob/main/examples/next-prisma-websockets-starter/src/pages/api/auth/%5B...nextauth%5D.ts) під час розробки.
diff --git a/www/src/pages/zh-hans/folder-structure-pages.mdx b/www/src/pages/zh-hans/folder-structure-pages.mdx
index 3ceb055d52..ce2fb44ad8 100644
--- a/www/src/pages/zh-hans/folder-structure-pages.mdx
+++ b/www/src/pages/zh-hans/folder-structure-pages.mdx
@@ -185,9 +185,9 @@ root.ts 文件用于合并 tRPC 子路由并将它们导出为一个单一的路
http://localhost:3000/api/auth/callback/discord
)
- 保存你的更改
- 在开发和生产环境使用同一个 Discord 应用是可行的,但不鼓励这么做。你应该也考虑在开发阶段 [模拟认证服务](https://github.com/trpc/trpc/blob/main/examples/next-prisma-websockets-starter/src/pages/api/auth/%5B...nextauth%5D.ts)。