chore(docs): update examples for nextjs 15 breaking changes

cookies() is now asynchronous
This commit is contained in:
Charis
2024-10-30 10:13:57 -04:00
committed by GitHub
parent 881d8a333b
commit 652c4288e6
15 changed files with 99 additions and 100 deletions
@@ -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')
}
+16 -16
View File
@@ -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('/')
}
+12 -13
View File
@@ -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>
);
)
}
+11 -11
View File
@@ -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() {
},
}
)
}
}