Skip to content
Snippets Groups Projects
Commit d032c0c7 authored by Yusuf Akgül's avatar Yusuf Akgül :hatching_chick:
Browse files

beg auth change

parent e627e255
No related branches found
No related tags found
1 merge request!19Feat.auth fixes
Showing
with 452 additions and 295 deletions
import { LoginForm } from '@/components/auth-login-form'
import { Icons } from '@/components/icons'
import { GameUnityLogo } from '@/components/logo'
import { buttonVariants } from '@/components/ui/button'
import { UserAuthForm } from '@/components/user-auth-form'
import { cn } from '@/lib/utils'
import Link from 'next/link'
export const metadata = {
title: "Login",
description: "Login to your account",
}
export default function LoginPage() {
return (
<div className="h-screen w-screen flex justify-center items-center bg-slate-100">
<div className="sm:shadow-xl px-8 pb-8 pt-12 sm:bg-black rounded-xl space-y-12">
<h1 className="font-semibold text-2xl">Login</h1>
<LoginForm />
<p className="text-center">
Need to create an account?{' '}
<Link className="text-indigo-500 hover:underline" href="/signup">
Create Account
</Link>{' '}
<div className="container flex min-h-screen w-screen flex-col items-center justify-center">
<Link
href="/"
className={cn(
buttonVariants({ variant: "ghost" }),
"absolute left-4 top-4 md:left-8 md:top-8"
)}
>
<>
<Icons.chevronLeft />
Back
</>
</Link>
<div className="mx-auto flex w-full flex-col justify-center space-y-6 sm:w-[350px]">
<div className="flex flex-col items-center space-y-2 text-center">
<GameUnityLogo className="h-10 w-10" />
<h1 className="text-2xl font-semibold tracking-tight">
Welcome back
</h1>
<p className="text-sm text-muted-foreground">
Enter your email to sign in to your account
</p>
</div>
<UserAuthForm type='login' />
<p className="px-8 text-center text-sm text-muted-foreground">
<Link
href="/signup"
className="hover:text-brand underline underline-offset-4"
>
Don&apos;t have an account? Sign Up
</Link>
</p>
</div>
</div>
......
import { SignupForm } from '@/components/auth-signup-form'
import { GameUnityLogo } from '@/components/logo'
import { buttonVariants } from '@/components/ui/button'
import { UserAuthForm } from '@/components/user-auth-form'
import { cn } from '@/lib/utils'
import Link from 'next/link'
export const metadata = {
title: "Create an account",
description: "Create an account to get started.",
}
export default function SignupPage() {
return (
<div className="h-screen w-screen flex justify-center items-center bg-slate-100">
<div className="sm:shadow-xl px-8 pb-8 pt-12 sm:bg-black rounded-xl space-y-12">
<h1 className="font-semibold text-2xl">Create your Account</h1>
<SignupForm />
<p className="text-center">
Have an account?{' '}
<Link className="text-indigo-500 hover:underline" href="/login">
Sign in
</Link>{' '}
</p>
<div className="container grid h-screen w-screen flex-col items-center justify-center lg:max-w-none lg:grid-cols-2 lg:px-0">
<Link
href="/login"
className={cn(
buttonVariants({ variant: "ghost" }),
"absolute right-4 top-4 md:right-8 md:top-8"
)}
>
Login
</Link>
<div className="hidden h-full bg-muted lg:block" />
<div className="lg:p-8">
<div className="mx-auto flex w-full flex-col justify-center space-y-6 sm:w-[350px]">
<div className="flex flex-col items-center space-y-2 text-center">
<GameUnityLogo className="h-10 w-10" />
<h1 className="text-2xl font-semibold tracking-tight">
Create an account
</h1>
<p className="text-sm text-muted-foreground">
Give yourself a username, enter your email and password below to create an account
</p>
</div>
<UserAuthForm type='signup' />
<p className="px-8 text-center text-sm text-muted-foreground">
By clicking continue, you agree to our{" "}
<Link
href="/terms"
className="hover:text-brand underline underline-offset-4"
>
Terms of Service
</Link>{" "}
and{" "}
<Link
href="/privacy"
className="hover:text-brand underline underline-offset-4"
>
Privacy Policy
</Link>
.
</p>
</div>
</div>
</div>
)
......
import LikeButton from "@/components/like-button";
import PostMessageForm from "@/components/post-messages";
import { prisma } from "@/lib/db";
import { db } from "@/lib/db";
import { Prisma } from "@prisma/client";
/* export const revalidate = 5; */ // revalidate this page every 60 seconds
......@@ -12,7 +12,7 @@ type messageItemProps = {
export default async function HomePage() {
let messages = null
try {
messages = await prisma.post.findMany({
messages = await db.post.findMany({
orderBy: {
createdAt: "desc"
}
......
import { authOptions } from "@/app/api/auth/[...nextauth]/route";
import FollowersList from "@/components/following-users";
import { getServerSession } from "next-auth";
export default async function Followers() {
const session = await getServerSession(authOptions);
// const session = await getServerSession(authOptions);
if (!session) {
return <div>Loading...</div>;
}
// if (!session) {
// return <div>Loading...</div>;
// }
return (
<div>
<h1>Followers Page WIP</h1>
<FollowersList userId={parseFloat(session.user?.id)} />
{/* <FollowersList userId={parseFloat(session.user?.id)} /> */}
</div>
)
}
\ No newline at end of file
......@@ -4,3 +4,4 @@ import NextAuth from 'next-auth'
const handler = NextAuth(authOptions)
export { handler as GET, handler as POST }
import { prisma } from "@/lib/db"
import { db } from "@/lib/db"
import { Prisma } from "@prisma/client"
type likeType = Prisma.LikeUncheckedCreateInput
......@@ -12,7 +12,7 @@ export async function putLike(like: likeType): Promise<likeType | undefined> {
// if exists delete
// if not create
try {
const actualLike = await prisma.like.findFirst({
const actualLike = await db.like.findFirst({
where: {
id: like.id,
postId: like.postId,
......@@ -25,13 +25,13 @@ export async function putLike(like: likeType): Promise<likeType | undefined> {
throw Error("Message was not liked by this user")
}
await prisma.like.delete({
await db.like.delete({
where: {
id: actualLike.id
}
})
const msg = await prisma.post.update({
const msg = await db.post.update({
where: {
id: like.postId
},
......@@ -43,14 +43,14 @@ export async function putLike(like: likeType): Promise<likeType | undefined> {
return undefined;
} catch {
const createdLike = await prisma.like.create({
const createdLike = await db.like.create({
data: {
postId: like.postId,
userId: like.userId
}
})
const updatedMessage = await prisma.post.update({
const updatedMessage = await db.post.update({
where: {
id: like.postId
},
......
import { authOptions } from "@/lib/auth";
import { prisma } from "@/lib/db";
import { db } from "@/lib/db";
import { Prisma } from "@prisma/client";
import { getServerSession } from "next-auth/next";
import { revalidatePath } from "next/cache";
......@@ -20,11 +20,11 @@ export async function POST(req: NextRequest) {
console.log("router data: " + data.content, "status:")
try {
await prisma.post.create({
await db.post.create({
/* data: data */
data: {
content: data.content,
userId: parseInt(userId),
userId: userId,
published: true
}
})
......@@ -34,7 +34,7 @@ export async function POST(req: NextRequest) {
return NextResponse.json({ status: 201, message: 'Message Created' })
} catch (error) {
} catch (error: any) {
console.log("fail" + error);
}
console.log("post")
......@@ -49,7 +49,7 @@ export async function GET(req: NextRequest, res: NextResponse) {
}
try {
const messages = await prisma.post.findMany({
const messages = await db.post.findMany({
orderBy: {
createdAt: "desc"
}
......
import { prisma } from '@/lib/db'
import { db } from '@/lib/db'
import { hash } from 'bcrypt'
import { NextResponse } from 'next/server'
export async function POST(req: Request) {
try {
const { email, password } = await req.json()
const { username, email, password } = await req.json()
const hashed = await hash(password, 12)
const user = await prisma.user.create({
const user = await db.user.create({
data: {
username,
email,
password: hashed
}
})
return NextResponse.json({
user: {
email: user.email
}
username: user.username,
email: user.email
})
} catch (err: any) {
return new NextResponse(
JSON.stringify({
error: err.message
}),
{
status: 500
}
return new NextResponse(JSON.stringify({
error: err.message
}), { status: 500 }
)
}
}
\ No newline at end of file
import { NextApiRequest, NextApiResponse } from "next";
import { prisma } from "@/lib/db";
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method !== 'GET') {
return res.status(405).end();
}
try {
const { userId } = req.query;
if (!userId || typeof userId !== 'string') {
throw new Error('Invalid ID');
}
const existingUser = await prisma.user.findUnique({
where: {
id: +userId
}
});
return res.status(200).json({ ...existingUser });
} catch (error) {
console.log(error);
return res.status(400).end();
}
};
\ No newline at end of file
import { NextApiRequest, NextApiResponse } from "next";
import { prisma } from "@/lib/db";
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method !== 'GET') {
return res.status(405).end();
}
try {
const users = await prisma.user.findMany({
orderBy: {
createdAt: 'desc'
}
});
return res.status(200).json(users);
} catch (error) {
console.log(error);
return res.status(400).end();
}
}
\ No newline at end of file
'use client'
import { Alert } from '@/components/ui/alert'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { signIn } from 'next-auth/react'
import { useRouter, useSearchParams } from 'next/navigation'
import { useState } from 'react'
export const LoginForm = () => {
const router = useRouter()
const searchParams = useSearchParams()
const callbackUrl = searchParams.get('callbackUrl') || '/home'
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [error, setError] = useState('')
const onSubmit = async (e: React.FormEvent) => {
e.preventDefault()
try {
const res = await signIn('credentials', {
redirect: false,
email,
password,
callbackUrl
})
console.log('Res', res)
if (!res?.error) {
router.push(callbackUrl)
} else {
setError('Invalid email or password')
}
} catch (err: any) { }
}
return (
<form onSubmit={onSubmit} className="space-y-12 w-full sm:w-[400px]">
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="email">Email</Label>
<Input
className="w-full"
required
value={email}
onChange={(e) => setEmail(e.target.value)}
id="email"
type="email"
/>
</div>
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="password">Password</Label>
<Input
className="w-full"
required
value={password}
onChange={(e) => setPassword(e.target.value)}
id="password"
type="password"
/>
</div>
{error && <Alert>{error}</Alert>}
<div className="w-full">
<Button className="w-full" size="lg">
Login
</Button>
</div>
</form>
)
}
\ No newline at end of file
'use client'
import { Alert } from '@/components/ui/alert'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { signIn } from 'next-auth/react'
import { useState } from 'react'
export const SignupForm = () => {
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [error, setError] = useState<string | null>(null)
const onSubmit = async (e: React.FormEvent) => {
e.preventDefault()
try {
const res = await fetch('/api/signup', {
method: 'POST',
body: JSON.stringify({
email,
password
}),
headers: {
'Content-Type': 'application/json'
}
})
if (res.ok) {
signIn()
} else {
setError((await res.json()).error)
}
} catch (error: any) {
setError(error?.message)
}
}
return (
<form onSubmit={onSubmit} className="space-y-12 w-full sm:w-[400px]">
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="email">Email</Label>
<Input
className="w-full"
required
value={email}
onChange={(e) => setEmail(e.target.value)}
id="email"
type="email"
/>
</div>
<div className="grid w-full items-center gap-1.5">
<Label htmlFor="password">Password</Label>
<Input
className="w-full"
required
value={password}
onChange={(e) => setPassword(e.target.value)}
id="password"
type="password"
/>
</div>
{error && <Alert>{error}</Alert>}
<div className="w-full">
<Button className="w-full" size="lg">
Sign up
</Button>
</div>
</form>
)
}
\ No newline at end of file
......@@ -11,6 +11,7 @@ import {
File,
FileText,
Gamepad2,
Github,
Heart,
HelpCircle,
Home,
......@@ -71,12 +72,13 @@ export const Icons: IconsType = {
help: HelpCircle, // Help Nav
sun: SunMedium, // Light Mode Toggle Nav
moon: Moon, // Dark Mode Toggle Nav
arrowupline: ArrowUpToLine, // Back to Top Button with line
arrowdown: ArrowDown, // Descending Sort
heart: Heart, // Like Button
arrowupline: ArrowUpToLine, // Back to Top Button
chevronLeft: ChevronLeft, // Back Login Arrow
spinner: Loader2, // Loading Spinner
github: Github, // Github Icon
close: X,
spinner: Loader2,
chevronLeft: ChevronLeft,
chevronRight: ChevronRight,
trash: Trash,
post: FileText,
......
import { Icons } from "./icons";
export function GameUnityLogo({ className }: { className?: string }) {
return (
<>
<Icons.logo className={`dark:hidden ${className}`} />
<Icons.logoWhite className={`hidden dark:block ${className}`} />
</>
)
}
......@@ -4,10 +4,11 @@ import { Icons, IconsType } from "@/components/icons";
import { buttonVariants } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import { SidebarNavItem } from "@/types";
import { signIn, signOut, useSession } from "next-auth/react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { GameUnityLogo } from "./logo";
import { ModeToggle } from "./mode-toggle";
import {signIn, signOut, useSession } from "next-auth/react"
interface DashboardNavProps {
items: SidebarNavItem[]
......@@ -19,7 +20,7 @@ export default function DashboardNav({ items }: DashboardNavProps) {
if (!items?.length) {
return null
}
const isLoaded = true
const user = "test"
......@@ -27,8 +28,7 @@ export default function DashboardNav({ items }: DashboardNavProps) {
<nav className="grid items-start gap-2">
<div className="flex items-center">
<Link href="/" className={cn("rounded-full p-3 hover:bg-accent")}>
<Icons.logo className="h-7 w-7 dark:hidden" />
<Icons.logoWhite className="h-7 w-7 hidden dark:block" />
<GameUnityLogo className="h-8 w-8" />
</Link>
</div>
{session?.user && isLoaded && user ?
......@@ -64,14 +64,14 @@ export default function DashboardNav({ items }: DashboardNavProps) {
</div>
}
{session?.user &&
<>
<p className="text-sky-600"> {session?.user.name}</p>
<button className=" text-red-500" onClick={() => signOut()}>
Sign Out
</button>
</>
<>
<p className="text-sky-600"> {session?.user.name}</p>
<button className=" text-red-500" onClick={() => signOut()}>
Sign Out
</button>
</>
}
<ModeToggle />
<ModeToggle />
</nav>
)
}
\ No newline at end of file
'use client'
import { zodResolver } from "@hookform/resolvers/zod"
import { signIn } from 'next-auth/react'
import { useSearchParams } from 'next/navigation'
import { HTMLAttributes, useState } from 'react'
import { useForm } from 'react-hook-form'
import * as z from "zod"
import { Icons } from '@/components/icons'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { useToast } from '@/components/ui/use-toast'
import { cn } from '@/lib/utils'
import { userAuthSchema } from '@/lib/validations/auth'
import { ToastAction } from "./ui/toast"
interface UserAuthFormProps extends HTMLAttributes<HTMLDivElement> {
type: "login" | "signup"
}
type FormData = z.infer<typeof userAuthSchema>
export function UserAuthForm({ type, className, ...props }: UserAuthFormProps) {
const {
register,
handleSubmit,
formState: { errors },
} = useForm<FormData>({
resolver: zodResolver(userAuthSchema),
})
const [isLoading, setIsLoading] = useState<boolean>(false)
const [isGitHubLoading, setIsGitHubLoading] = useState<boolean>(false)
const searchParams = useSearchParams()
const { toast } = useToast()
async function onSubmit(data: FormData) {
setIsLoading(true)
if (type === "signup") {
const res = await fetch('/api/signup', {
method: 'POST',
body: JSON.stringify({
username: data.username,
email: data.email,
password: data.password
}),
headers: {
'Content-Type': 'application/json'
}
})
if (!res.ok) {
setIsLoading(false)
toast({
variant: "destructive",
title: "Uh oh! Something went wrong.",
description: "Your sign up request failed. Please try again.",
})
}
}
const signInResult = await signIn("credentials", {
username: data.username,
email: data.email,
password: data.password,
redirect: false,
callbackUrl: "/home",
});
setIsLoading(false)
if (!signInResult?.ok) {
toast({
variant: "destructive",
title: "Uh oh! Something went wrong.",
description: "Your log in request failed. Please try again.",
action: <ToastAction altText="Try again">Try again</ToastAction>,
})
}
// toast({
// title: "Check your email.",
// description: "We sent you a login link. Be sure to check your spam too.",
// })
}
return (
<>
<div className={cn("grid gap-6", className)} {...props}>
<form onSubmit={handleSubmit(onSubmit)}>
<div className="grid gap-2">
<div className="grid gap-1">
<Label className="sr-only" htmlFor="username">
Username
</Label>
<Input
id="username"
placeholder="Your username"
type="username"
autoCapitalize="none"
autoComplete="username"
autoCorrect="off"
disabled={isLoading || isGitHubLoading}
{...register("username")}
/>
{errors?.username && (
<p className="px-1 text-xs text-red-600">
{errors.username.message}
</p>
)}
</div>
{type === "signup" ? <div className="grid gap-1">
<Label className="sr-only" htmlFor="email">
Email
</Label>
<Input
id="email"
placeholder="Your email"
type="email"
autoCapitalize="none"
autoComplete="email"
autoCorrect="off"
disabled={isLoading || isGitHubLoading}
{...register("email")}
/>
{errors?.email && (
<p className="px-1 text-xs text-red-600">
{errors.email.message}
</p>
)}
</div> : null}
<div className="grid gap-1">
<Label className="sr-only" htmlFor="password">
Password
</Label>
<Input
id="password"
placeholder="Your password"
type="password"
autoCapitalize="none"
autoComplete="new-password"
autoCorrect="off"
disabled={isLoading || isGitHubLoading}
{...register("password")}
/>
{errors?.password && (
<p className="px-1 text-xs text-red-600">
{errors.password.message}
</p>
)}
</div>
<Button disabled={isLoading}>
{isLoading && (
<Icons.spinner className="mr-2 h-4 w-4 animate-spin" />
)}
{type === "signup" ? "Sign Up" : "Log In"}
</Button>
</div>
</form>
<div className="relative">
<div className="absolute inset-0 flex items-center">
<span className="w-full border-t" />
</div>
<div className="relative flex justify-center text-xs uppercase">
<span className="bg-background px-2 text-muted-foreground">
Or continue with
</span>
</div>
</div>
<Button
variant="outline"
type="button"
onClick={() => {
setIsGitHubLoading(true)
signIn("github")
}}
disabled={isLoading || isGitHubLoading}
>
{isGitHubLoading ? (
<Icons.spinner className="mr-2 h-4 w-4 animate-spin" />
) : (
<Icons.github className="mr-2 h-4 w-4" />
)}{" "}
Github
</Button>
</div>
</>
)
}
\ No newline at end of file
......@@ -3,19 +3,19 @@ import Link from "next/link";
import FollowButton from "./following-button";
// this is a single user helper-component, only for design purposes
export default function FollowUser({ id, followId, userName, image }: { id: number, followId: number, userName: string, image: { url: string } }) {
export default function FollowUser({ id, followId, username, image }: { id: number, followId: number, username: string, image: { url: string } }) {
return (
<div>
<Link href={`/user/${id}`}>
<div className="">
<Image
src={image.url}
alt={userName}
alt={username}
width={50}
height={50}
priority={true} />
</div>
<p>{userName}</p>
<p>{username}</p>
<FollowButton userId={id} followerId={followId} />
</Link>
</div>
......
env.mjs 0 → 100644
import { createEnv } from "@t3-oss/env-nextjs"
import { z } from "zod"
export const env = createEnv({
server: {
DATABASE_URL: z.string().min(1),
GITHUB_CLIENT_ID: z.string().min(1),
GITHUB_CLIENT_SECRET: z.string().min(1),
NEXTAUTH_URL: z.string().url().optional(),
NEXTAUTH_SECRET: z.string().min(1),
TWITCH_CLIENT_ID: z.string().min(1),
TWITCH_CLIENT_SECRET: z.string().min(1),
TWITCH_AUTH_BASE_URL: z.string().url().optional(),
IGDB_BASE_URL: z.string().url().optional(),
IGDB_IMG_BASE_URL: z.string().url().optional(),
},
client: {
NEXT_PUBLIC_APP_URL: z.string().min(1),
},
runtimeEnv: {
DATABASE_URL: process.env.DATABASE_URL,
GITHUB_CLIENT_ID: process.env.GITHUB_CLIENT_ID,
GITHUB_CLIENT_SECRET: process.env.GITHUB_CLIENT_SECRET,
NEXTAUTH_URL: process.env.NEXTAUTH_URL,
NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET,
NEXT_PUBLIC_APP_URL: process.env.NEXT_PUBLIC_APP_URL,
TWITCH_CLIENT_ID: process.env.TWITCH_CLIENT_ID,
TWITCH_CLIENT_SECRET: process.env.TWITCH_CLIENT_SECRET,
TWITCH_AUTH_BASE_URL: process.env.TWITCH_AUTH_BASE_URL,
IGDB_BASE_URL: process.env.IGDB_BASE_URL,
IGDB_IMG_BASE_URL: process.env.IGDB_IMG_BASE_URL,
},
})
\ No newline at end of file
import { env } from "@/env.mjs"
import { db } from "@/lib/db"
import { PrismaAdapter } from "@auth/prisma-adapter"
import { compare } from "bcrypt"
import { NextAuthOptions } from "next-auth"
import { Adapter } from "next-auth/adapters"
import CredentialsProvider from 'next-auth/providers/credentials'
import { prisma } from "./db"
import GitHubProvider from "next-auth/providers/github"
export const authOptions: NextAuthOptions = {
adapter: PrismaAdapter(db as any) as Adapter,
session: {
strategy: 'jwt'
},
pages: {
signIn: "/login",
},
providers: [
GitHubProvider({
clientId: env.GITHUB_CLIENT_ID as string,
clientSecret: env.GITHUB_CLIENT_SECRET as string,
}),
CredentialsProvider({
name: 'Sign in',
name: 'Login',
credentials: {
email: {
label: 'Email',
type: 'email',
placeholder: 'hello@example.com'
},
username: { label: 'Username', type: 'text' },
email: { label: 'Email', type: 'email', placeholder: 'hello@example.com' },
password: { label: 'Password', type: 'password' }
},
async authorize(credentials) {
if (!credentials?.email || !credentials.password) {
if (!credentials?.username || !credentials.email || !credentials.password) {
return null
}
const user = await prisma.user.findUnique({
let isUnique = false;
while (!isUnique) {
const existingUserName = await db.user.findUnique({
where: {
username: credentials.username
}
})
if (existingUserName) {
credentials.username = `${credentials.username}${Math.floor(Math.random() * 1000)}`
} else {
isUnique = true;
}
}
const user = await db.user.findUnique({
where: {
email: credentials.email
}
......@@ -43,34 +68,46 @@ export const authOptions: NextAuthOptions = {
}
return {
id: user.id + '',
id: user.id,
username: user.username,
email: user.email,
name: user.name,
}
}
})
],
secret: env.NEXTAUTH_SECRET,
callbacks: {
session: ({ session, token }) => {
console.log('Session Callback', { session, token })
return {
...session,
user: {
...session.user,
id: token.id,
}
async session({ token, session }) {
if (token) {
session.user.id = token.id + ''
session.user.name = token.name
session.user.email = token.email
session.user.image = token.picture
}
return session
},
jwt: ({ token, user }) => {
console.log('JWT Callback', { token, user })
if (user) {
const u = user as unknown as any
return {
...token,
id: u.id,
async jwt({ token, user }) {
const dbUser = await db.user.findFirst({
where: {
email: token.email,
},
})
if (!dbUser) {
if (user) {
token.id = user?.id
}
return token
}
return {
id: dbUser.id,
name: dbUser.name,
email: dbUser.email,
picture: dbUser.image,
}
return token
}
}
}
\ No newline at end of file
import { PrismaClient } from '@prisma/client'
import { PrismaClient } from "@prisma/client"
const globalForPrisma = global as unknown as {
prisma: PrismaClient | undefined
declare global {
// eslint-disable-next-line no-var
var cachedPrisma: PrismaClient
}
export const prisma =
globalForPrisma.prisma ??
new PrismaClient({
// log: ['query'],
})
let prisma: PrismaClient
if (process.env.NODE_ENV === "production") {
prisma = new PrismaClient()
} else {
if (!global.cachedPrisma) {
global.cachedPrisma = new PrismaClient()
}
prisma = global.cachedPrisma
}
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
\ No newline at end of file
export const db = prisma
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment