mirror of
https://github.com/supabase/supabase.git
synced 2026-05-06 08:56:46 -04:00
chore(docs): update examples for nextjs 15 breaking changes
cookies() is now asynchronous
This commit is contained in:
@@ -118,8 +118,8 @@ export function createClient() {
|
||||
import { createServerClient } from '@supabase/ssr'
|
||||
import { cookies } from 'next/headers'
|
||||
|
||||
export function createClient() {
|
||||
const cookieStore = cookies()
|
||||
export async function createClient() {
|
||||
const cookieStore = await cookies()
|
||||
|
||||
// Create a server's supabase client with newly configured cookie,
|
||||
// which could be used to maintain user's session
|
||||
@@ -763,7 +763,7 @@ import { revalidatePath } from 'next/cache'
|
||||
import { NextResponse } from 'next/server'
|
||||
|
||||
export async function POST(req) {
|
||||
const supabase = createClient()
|
||||
const supabase = await createClient()
|
||||
|
||||
// Check if a user's logged in
|
||||
const {
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import { type EmailOtpType } from "@supabase/supabase-js"
|
||||
import { type NextRequest, NextResponse } from "next/server"
|
||||
import { createClient } from "@/utils/supabase/server"
|
||||
import { redirect } from "next/navigation"
|
||||
import { type EmailOtpType } from '@supabase/supabase-js'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { createClient } from '@/utils/supabase/server'
|
||||
import { redirect } from 'next/navigation'
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
const { searchParams } = new URL(request.url)
|
||||
const token_hash = searchParams.get("token_hash")
|
||||
const type = searchParams.get("type") as EmailOtpType | null
|
||||
const next = searchParams.get("next") ?? "/"
|
||||
const token_hash = searchParams.get('token_hash')
|
||||
const type = searchParams.get('type') as EmailOtpType | null
|
||||
const next = searchParams.get('next') ?? '/'
|
||||
|
||||
if (token_hash && type) {
|
||||
const supabase = createClient()
|
||||
const supabase = await createClient()
|
||||
|
||||
const { error } = await supabase.auth.verifyOtp({
|
||||
type,
|
||||
@@ -23,5 +23,5 @@ export async function GET(request: NextRequest) {
|
||||
}
|
||||
|
||||
// redirect the user to an error page with some instructions
|
||||
redirect("/error")
|
||||
redirect('/error')
|
||||
}
|
||||
|
||||
@@ -1,45 +1,45 @@
|
||||
"use server"
|
||||
'use server'
|
||||
|
||||
import { revalidatePath } from "next/cache"
|
||||
import { redirect } from "next/navigation"
|
||||
import { createClient } from "@/utils/supabase/server"
|
||||
import { revalidatePath } from 'next/cache'
|
||||
import { redirect } from 'next/navigation'
|
||||
import { createClient } from '@/utils/supabase/server'
|
||||
|
||||
export async function signIn(formData: FormData) {
|
||||
const supabase = createClient()
|
||||
const supabase = await createClient()
|
||||
|
||||
// type-casting here for convenience
|
||||
// in practice, you should validate your inputs
|
||||
const data = {
|
||||
email: formData.get("email") as string,
|
||||
password: formData.get("password") as string,
|
||||
email: formData.get('email') as string,
|
||||
password: formData.get('password') as string,
|
||||
}
|
||||
|
||||
const { error } = await supabase.auth.signInWithPassword(data)
|
||||
|
||||
if (error) {
|
||||
redirect("/error")
|
||||
redirect('/error')
|
||||
}
|
||||
|
||||
revalidatePath("/", "layout")
|
||||
redirect("/")
|
||||
revalidatePath('/', 'layout')
|
||||
redirect('/')
|
||||
}
|
||||
|
||||
export async function signUp(formData: FormData) {
|
||||
const supabase = createClient()
|
||||
const supabase = await createClient()
|
||||
|
||||
// type-casting here for convenience
|
||||
// in practice, you should validate your inputs
|
||||
const data = {
|
||||
email: formData.get("email") as string,
|
||||
password: formData.get("password") as string,
|
||||
email: formData.get('email') as string,
|
||||
password: formData.get('password') as string,
|
||||
}
|
||||
|
||||
const { error } = await supabase.auth.signUp(data)
|
||||
|
||||
if (error) {
|
||||
redirect("/error")
|
||||
redirect('/error')
|
||||
}
|
||||
|
||||
revalidatePath("/", "layout")
|
||||
redirect("/")
|
||||
revalidatePath('/', 'layout')
|
||||
redirect('/')
|
||||
}
|
||||
|
||||
@@ -1,27 +1,26 @@
|
||||
import DeployButton from "@/components/DeployButton";
|
||||
import AuthButton from "@/components/AuthButton";
|
||||
import { createClient } from "@/utils/supabase/server";
|
||||
import FetchDataSteps from "@/components/tutorial/FetchDataSteps";
|
||||
import Header from "@/components/Header";
|
||||
import { redirect } from "next/navigation";
|
||||
import DeployButton from '@/components/DeployButton'
|
||||
import AuthButton from '@/components/AuthButton'
|
||||
import { createClient } from '@/utils/supabase/server'
|
||||
import FetchDataSteps from '@/components/tutorial/FetchDataSteps'
|
||||
import Header from '@/components/Header'
|
||||
import { redirect } from 'next/navigation'
|
||||
|
||||
export default async function ProtectedPage() {
|
||||
const supabase = createClient();
|
||||
const supabase = await createClient()
|
||||
|
||||
const {
|
||||
data: { user },
|
||||
} = await supabase.auth.getUser();
|
||||
} = await supabase.auth.getUser()
|
||||
|
||||
if (!user) {
|
||||
return redirect("/login");
|
||||
return redirect('/login')
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex-1 w-full flex flex-col gap-20 items-center">
|
||||
<div className="w-full">
|
||||
<div className="py-6 font-bold bg-purple-950 text-center">
|
||||
This is a protected page that you can only see as an authenticated
|
||||
user
|
||||
This is a protected page that you can only see as an authenticated user
|
||||
</div>
|
||||
<nav className="w-full flex justify-center border-b border-b-foreground/10 h-16">
|
||||
<div className="w-full max-w-4xl flex justify-between items-center p-3 text-sm">
|
||||
@@ -41,7 +40,7 @@ export default async function ProtectedPage() {
|
||||
|
||||
<footer className="w-full border-t border-t-foreground/10 p-8 flex justify-center text-center text-xs">
|
||||
<p>
|
||||
Powered by{" "}
|
||||
Powered by{' '}
|
||||
<a
|
||||
href="https://supabase.com/?utm_source=create-next-app&utm_medium=template&utm_term=nextjs"
|
||||
target="_blank"
|
||||
@@ -53,5 +52,5 @@ export default async function ProtectedPage() {
|
||||
</p>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import { createClient } from "@/utils/supabase/server";
|
||||
import Link from "next/link";
|
||||
import { redirect } from "next/navigation";
|
||||
import { createClient } from '@/utils/supabase/server'
|
||||
import Link from 'next/link'
|
||||
import { redirect } from 'next/navigation'
|
||||
|
||||
export default async function AuthButton() {
|
||||
const supabase = createClient();
|
||||
const supabase = await createClient()
|
||||
|
||||
const {
|
||||
data: { user },
|
||||
} = await supabase.auth.getUser();
|
||||
} = await supabase.auth.getUser()
|
||||
|
||||
const signOut = async () => {
|
||||
"use server";
|
||||
'use server'
|
||||
|
||||
const supabase = createClient();
|
||||
await supabase.auth.signOut();
|
||||
return redirect("/login");
|
||||
};
|
||||
const supabase = createClient()
|
||||
await supabase.auth.signOut()
|
||||
return redirect('/login')
|
||||
}
|
||||
|
||||
return user ? (
|
||||
<div className="flex items-center gap-4">
|
||||
@@ -33,5 +33,5 @@ export default async function AuthButton() {
|
||||
>
|
||||
Login
|
||||
</Link>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { createServerClient, type CookieOptions } from "@supabase/ssr"
|
||||
import { cookies } from "next/headers"
|
||||
import { createServerClient } from '@supabase/ssr'
|
||||
import { cookies } from 'next/headers'
|
||||
|
||||
export function createClient() {
|
||||
const cookieStore = cookies()
|
||||
export async function createClient() {
|
||||
const cookieStore = await cookies()
|
||||
|
||||
return createServerClient(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import { createClient } from "@/utils/supabase/server";
|
||||
import { NextResponse } from "next/server";
|
||||
import { createClient } from '@/utils/supabase/server'
|
||||
import { NextResponse } from 'next/server'
|
||||
|
||||
export async function GET(request: Request) {
|
||||
// The `/auth/callback` route is required for the server-side auth flow implemented
|
||||
// by the SSR package. It exchanges an auth code for the user's session.
|
||||
// https://supabase.com/docs/guides/auth/server-side/nextjs
|
||||
const requestUrl = new URL(request.url);
|
||||
const code = requestUrl.searchParams.get("code");
|
||||
const origin = requestUrl.origin;
|
||||
const requestUrl = new URL(request.url)
|
||||
const code = requestUrl.searchParams.get('code')
|
||||
const origin = requestUrl.origin
|
||||
|
||||
if (code) {
|
||||
const supabase = createClient();
|
||||
await supabase.auth.exchangeCodeForSession(code);
|
||||
const supabase = await createClient()
|
||||
await supabase.auth.exchangeCodeForSession(code)
|
||||
}
|
||||
|
||||
// URL to redirect to after sign up process completes
|
||||
return NextResponse.redirect(`${origin}/protected`);
|
||||
return NextResponse.redirect(`${origin}/protected`)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ export default function Login({ searchParams }: { searchParams: { message: strin
|
||||
|
||||
const email = formData.get('email') as string
|
||||
const password = formData.get('password') as string
|
||||
const supabase = createClient()
|
||||
const supabase = await createClient()
|
||||
|
||||
const { error } = await supabase.auth.signInWithPassword({
|
||||
email,
|
||||
@@ -30,7 +30,7 @@ export default function Login({ searchParams }: { searchParams: { message: strin
|
||||
const origin = headers().get('origin')
|
||||
const email = formData.get('email') as string
|
||||
const password = formData.get('password') as string
|
||||
const supabase = createClient()
|
||||
const supabase = await createClient()
|
||||
|
||||
const { error } = await supabase.auth.signUp({
|
||||
email,
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
import { createClient } from "@/utils/supabase/server";
|
||||
import Link from "next/link";
|
||||
import { redirect } from "next/navigation";
|
||||
import { createClient } from '@/utils/supabase/server'
|
||||
import Link from 'next/link'
|
||||
import { redirect } from 'next/navigation'
|
||||
|
||||
export default async function AuthButton() {
|
||||
const supabase = createClient();
|
||||
const supabase = await createClient()
|
||||
|
||||
const {
|
||||
data: { user },
|
||||
} = await supabase.auth.getUser();
|
||||
} = await supabase.auth.getUser()
|
||||
|
||||
const signOut = async () => {
|
||||
"use server";
|
||||
'use server'
|
||||
|
||||
const supabase = createClient();
|
||||
await supabase.auth.signOut();
|
||||
return redirect("/login");
|
||||
};
|
||||
const supabase = createClient()
|
||||
await supabase.auth.signOut()
|
||||
return redirect('/login')
|
||||
}
|
||||
|
||||
return user ? (
|
||||
<div className="flex items-center gap-4">
|
||||
{user.email}{" "}
|
||||
{user.email}{' '}
|
||||
<form action={signOut}>
|
||||
<button className="py-2 px-4 rounded-md no-underline bg-btn-background hover:bg-btn-background-hover">
|
||||
Logout
|
||||
@@ -33,5 +33,5 @@ export default async function AuthButton() {
|
||||
>
|
||||
Login
|
||||
</Link>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { createServerClient, type CookieOptions } from "@supabase/ssr";
|
||||
import { cookies } from "next/headers";
|
||||
import { createServerClient, type CookieOptions } from '@supabase/ssr'
|
||||
import { cookies } from 'next/headers'
|
||||
|
||||
export const createClient = () => {
|
||||
const cookieStore = cookies();
|
||||
export const createClient = async () => {
|
||||
const cookieStore = await cookies()
|
||||
|
||||
return createServerClient(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||
@@ -10,11 +10,11 @@ export const createClient = () => {
|
||||
{
|
||||
cookies: {
|
||||
get(name: string) {
|
||||
return cookieStore.get(name)?.value;
|
||||
return cookieStore.get(name)?.value
|
||||
},
|
||||
set(name: string, value: string, options: CookieOptions) {
|
||||
try {
|
||||
cookieStore.set({ name, value, ...options });
|
||||
cookieStore.set({ name, value, ...options })
|
||||
} catch (error) {
|
||||
// The `set` method was called from a Server Component.
|
||||
// This can be ignored if you have middleware refreshing
|
||||
@@ -23,7 +23,7 @@ export const createClient = () => {
|
||||
},
|
||||
remove(name: string, options: CookieOptions) {
|
||||
try {
|
||||
cookieStore.set({ name, value: "", ...options });
|
||||
cookieStore.set({ name, value: '', ...options })
|
||||
} catch (error) {
|
||||
// The `delete` method was called from a Server Component.
|
||||
// This can be ignored if you have middleware refreshing
|
||||
@@ -31,6 +31,6 @@ export const createClient = () => {
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
};
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,11 +2,11 @@ import AccountForm from './account-form'
|
||||
import { createClient } from '@/utils/supabase/server'
|
||||
|
||||
export default async function Account() {
|
||||
const supabase = createClient()
|
||||
const supabase = await createClient()
|
||||
|
||||
const {
|
||||
data: { user },
|
||||
} = await supabase.auth.getUser()
|
||||
|
||||
return <AccountForm user={user} />
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ export async function GET(request: NextRequest) {
|
||||
redirectTo.searchParams.delete('type')
|
||||
|
||||
if (token_hash && type) {
|
||||
const supabase = createClient()
|
||||
const supabase = await createClient()
|
||||
|
||||
const { error } = await supabase.auth.verifyOtp({
|
||||
type,
|
||||
@@ -32,4 +32,4 @@ export async function GET(request: NextRequest) {
|
||||
// return the user to an error page with some instructions
|
||||
redirectTo.pathname = '/error'
|
||||
return NextResponse.redirect(redirectTo)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { revalidatePath } from 'next/cache'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
const supabase = createClient()
|
||||
const supabase = await createClient()
|
||||
|
||||
// Check if a user's logged in
|
||||
const {
|
||||
@@ -18,4 +18,4 @@ export async function POST(req: NextRequest) {
|
||||
return NextResponse.redirect(new URL('/login', req.url), {
|
||||
status: 302,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { redirect } from 'next/navigation'
|
||||
import { createClient } from '@/utils/supabase/server'
|
||||
|
||||
export async function login(formData: FormData) {
|
||||
const supabase = createClient()
|
||||
const supabase = await createClient()
|
||||
|
||||
// type-casting here for convenience
|
||||
// in practice, you should validate your inputs
|
||||
@@ -26,7 +26,7 @@ export async function login(formData: FormData) {
|
||||
}
|
||||
|
||||
export async function signup(formData: FormData) {
|
||||
const supabase = createClient()
|
||||
const supabase = await createClient()
|
||||
|
||||
// type-casting here for convenience
|
||||
// in practice, you should validate your inputs
|
||||
@@ -43,4 +43,4 @@ export async function signup(formData: FormData) {
|
||||
|
||||
revalidatePath('/', 'layout')
|
||||
redirect('/account')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { createServerClient } from '@supabase/ssr'
|
||||
import { cookies } from 'next/headers'
|
||||
|
||||
export function createClient() {
|
||||
const cookieStore = cookies()
|
||||
export async function createClient() {
|
||||
const cookieStore = await cookies()
|
||||
|
||||
// Create a server's supabase client with newly configured cookie,
|
||||
// which could be used to maintain user's session
|
||||
@@ -28,4 +28,4 @@ export function createClient() {
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user