Chore: simplify with-supabase example (#57562)
### What? [1] Simplify example [2] Refactor `delete` method to use `cookies.set` ### Why? [1] Make it easier to follow [2] Fix build errors ### How? [1] Adding comments and abstracting code into helper functions [2] Setting cookie to empty value when removed --------- Co-authored-by: Lee Robinson <me@leerob.io>
This commit is contained in:
parent
e0cf4e2ebd
commit
75958bbc46
5 changed files with 89 additions and 68 deletions
|
@ -10,6 +10,8 @@ export default async function Index() {
|
|||
const cookieStore = cookies()
|
||||
|
||||
const canInitSupabaseClient = () => {
|
||||
// This function is just for the interactive tutorial.
|
||||
// Feel free to remove it once you have Supabase connected.
|
||||
try {
|
||||
createClient(cookieStore)
|
||||
return true
|
||||
|
|
|
@ -4,21 +4,24 @@ import Code from '@/components/Code'
|
|||
|
||||
const create = `
|
||||
create table notes (
|
||||
id uuid default gen_random_uuid() primary key,
|
||||
id serial primary key,
|
||||
title text
|
||||
);
|
||||
|
||||
insert into notes(title)
|
||||
values('Today I connected Next.js to Supabase. It was awesome!');
|
||||
values
|
||||
('Today I created a Supabase project.'),
|
||||
('I added some data and queried it from Next.js.'),
|
||||
('It was awesome!');
|
||||
`.trim()
|
||||
|
||||
const server = `
|
||||
import { createClient } from '@/utils/supabase/server'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
import { cookies } from 'next/headers'
|
||||
|
||||
export default async function Page() {
|
||||
const supabase = createClient()
|
||||
const cookieStore = cookies()
|
||||
const supabase = createClient(cookieStore)
|
||||
const { data: notes } = await supabase.from('notes').select()
|
||||
|
||||
return <pre>{JSON.stringify(notes, null, 2)}</pre>
|
||||
|
@ -93,11 +96,15 @@ export default function SignUpUserSteps() {
|
|||
|
||||
<Step title="Query Supabase data from Next.js">
|
||||
<p>
|
||||
Create a Supabase client and query data from an Async Server
|
||||
Component.
|
||||
To create a Supabase client and query data from an Async Server
|
||||
Component, create a new page.tsx file at{' '}
|
||||
<span className="px-2 py-1 rounded-md bg-foreground/20 text-foreground/80">
|
||||
/app/notes/page.tsx
|
||||
</span>{' '}
|
||||
and add the following.
|
||||
</p>
|
||||
<Code code={server} />
|
||||
<p>Alternatively, you can use a client component.</p>
|
||||
<p>Alternatively, you can use a Client Component.</p>
|
||||
<Code code={client} />
|
||||
</Step>
|
||||
|
||||
|
|
|
@ -1,74 +1,25 @@
|
|||
import { createServerClient, type CookieOptions } from '@supabase/ssr'
|
||||
import { NextResponse, type NextRequest } from 'next/server'
|
||||
import { createClient } from '@/utils/supabase/middleware'
|
||||
|
||||
export async function middleware(request: NextRequest) {
|
||||
// Create an unmodified response
|
||||
let response = NextResponse.next({
|
||||
request: {
|
||||
headers: request.headers,
|
||||
},
|
||||
})
|
||||
|
||||
try {
|
||||
// Create a Supabase client configured to use cookies
|
||||
const supabase = createServerClient(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
||||
{
|
||||
cookies: {
|
||||
get(name: string) {
|
||||
return request.cookies.get(name)?.value
|
||||
},
|
||||
set(name: string, value: string, options: CookieOptions) {
|
||||
// If the cookie is updated, update the cookies for the request and response
|
||||
request.cookies.set({
|
||||
name,
|
||||
value,
|
||||
...options,
|
||||
})
|
||||
response = NextResponse.next({
|
||||
request: {
|
||||
headers: request.headers,
|
||||
},
|
||||
})
|
||||
response.cookies.set({
|
||||
name,
|
||||
value,
|
||||
...options,
|
||||
})
|
||||
},
|
||||
remove(name, options) {
|
||||
// If the cookie is removed, update the cookies for the request and response
|
||||
request.cookies.delete({
|
||||
name,
|
||||
...options,
|
||||
})
|
||||
response = NextResponse.next({
|
||||
request: {
|
||||
headers: request.headers,
|
||||
},
|
||||
})
|
||||
response.cookies.delete({
|
||||
name,
|
||||
...options,
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
// This `try/catch` block is only here for the interactive tutorial.
|
||||
// Feel free to remove once you have Supabase connected.
|
||||
const { supabase, response } = createClient(request)
|
||||
|
||||
// Refresh session if expired - required for Server Components
|
||||
// https://supabase.com/docs/guides/auth/auth-helpers/nextjs#managing-session-with-middleware
|
||||
await supabase.auth.getSession()
|
||||
|
||||
// If the session was refreshed, the request and response cookies will have been updated
|
||||
// If the session was not refreshed, the request and response cookies will be unchanged
|
||||
return response
|
||||
} catch (e) {
|
||||
// If you are here, a Supabase client could not be created!
|
||||
// This is likely because you have not set up environment variables.
|
||||
// TODO: Feel free to remove this `try catch` block once you have
|
||||
// your Next.js app connected to your Supabase project.
|
||||
return response
|
||||
// Check out http://localhost:3000 for Next Steps.
|
||||
return NextResponse.next({
|
||||
request: {
|
||||
headers: request.headers,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
61
examples/with-supabase/utils/supabase/middleware.ts
Normal file
61
examples/with-supabase/utils/supabase/middleware.ts
Normal file
|
@ -0,0 +1,61 @@
|
|||
import { createServerClient, type CookieOptions } from '@supabase/ssr'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
export const createClient = (request: NextRequest) => {
|
||||
// Create an unmodified response
|
||||
let response = NextResponse.next({
|
||||
request: {
|
||||
headers: request.headers,
|
||||
},
|
||||
})
|
||||
|
||||
const supabase = createServerClient(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
||||
{
|
||||
cookies: {
|
||||
get(name: string) {
|
||||
return request.cookies.get(name)?.value
|
||||
},
|
||||
set(name: string, value: string, options: CookieOptions) {
|
||||
// If the cookie is updated, update the cookies for the request and response
|
||||
request.cookies.set({
|
||||
name,
|
||||
value,
|
||||
...options,
|
||||
})
|
||||
response = NextResponse.next({
|
||||
request: {
|
||||
headers: request.headers,
|
||||
},
|
||||
})
|
||||
response.cookies.set({
|
||||
name,
|
||||
value,
|
||||
...options,
|
||||
})
|
||||
},
|
||||
remove(name: string, options: CookieOptions) {
|
||||
// If the cookie is removed, update the cookies for the request and response
|
||||
request.cookies.set({
|
||||
name,
|
||||
value: '',
|
||||
...options,
|
||||
})
|
||||
response = NextResponse.next({
|
||||
request: {
|
||||
headers: request.headers,
|
||||
},
|
||||
})
|
||||
response.cookies.set({
|
||||
name,
|
||||
value: '',
|
||||
...options,
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
return { supabase, response }
|
||||
}
|
|
@ -21,7 +21,7 @@ export const createClient = (cookieStore: ReturnType<typeof cookies>) => {
|
|||
},
|
||||
remove(name: string, options: CookieOptions) {
|
||||
try {
|
||||
cookieStore.delete({ name, ...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
|
||||
|
|
Loading…
Reference in a new issue