47 lines
1.6 KiB
TypeScript
47 lines
1.6 KiB
TypeScript
// packages/api-client/src/supabase-server.ts
|
|
// RSC/route handler용 Supabase 서버 클라이언트 팩토리.
|
|
// next/headers에 직접 의존하지 않고, 호출부에서 cookieStore를 주입.
|
|
// Database 제네릭 주입 (@supabase/ssr 0.10 + supabase-js 2.103 정합).
|
|
|
|
import { createServerClient, type CookieOptions } from '@supabase/ssr'
|
|
import type { Database } from './types'
|
|
import { requireSupabasePublicConfig } from './client'
|
|
|
|
/** next/headers cookies()가 반환하는 객체의 최소 인터페이스 */
|
|
export interface CookieStore {
|
|
getAll(): Array<{ name: string; value: string }>
|
|
set(name: string, value: string, options: CookieOptions): void
|
|
}
|
|
|
|
export function createSupabaseServerClient(
|
|
cookieStore: CookieStore,
|
|
): ReturnType<typeof createServerClient<Database>> {
|
|
const { url, anonKey } = requireSupabasePublicConfig({
|
|
url: process.env.NEXT_PUBLIC_SUPABASE_URL,
|
|
anonKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
|
|
})
|
|
|
|
return createServerClient<Database>(url, anonKey, {
|
|
cookies: {
|
|
getAll() {
|
|
return cookieStore.getAll()
|
|
},
|
|
setAll(cookiesToSet: Array<{ name: string; value: string; options: CookieOptions }>) {
|
|
try {
|
|
cookiesToSet.forEach(({ name, value, options }) => {
|
|
cookieStore.set(name, value, options)
|
|
})
|
|
} catch {
|
|
// RSC에서 set은 실패하지만 route handler에서는 성공
|
|
}
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
export function isSupabaseConfiguredServer(): boolean {
|
|
return Boolean(
|
|
process.env.NEXT_PUBLIC_SUPABASE_URL?.trim()
|
|
&& process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY?.trim(),
|
|
)
|
|
}
|