// server/supabase/functions/_shared/quota.ts // 티어별 기능 쿼터 확인 + 증가 // @ts-expect-error — Deno 런타임 import import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.39.7' export type Tier = 'free' | 'pro' | 'team' export type Feature = 'stt_transcribe' | 'llm_process' /** 일일 쿼터 정책 (-1 = 무제한) */ const DAILY_QUOTA: Record> = { free: { stt_transcribe: 50, llm_process: 50 }, pro: { stt_transcribe: -1, llm_process: -1 }, team: { stt_transcribe: -1, llm_process: -1 } } export interface QuotaCheck { allowed: boolean current: number limit: number tier: Tier } /** * 유저의 오늘 사용량을 확인하고 쿼터 초과 여부를 반환. * 실제 증가는 performQuotaConsume 호출 시 수행. */ export async function checkQuota( userId: string, feature: Feature, serviceRoleClient: ReturnType ): Promise { // 티어 조회 const { data: sub } = await serviceRoleClient .from('subscriptions') .select('tier') .eq('user_id', userId) .single() const tier: Tier = (sub?.tier as Tier) ?? 'free' const limit = DAILY_QUOTA[tier][feature] if (limit === -1) { return { allowed: true, current: 0, limit, tier } } // 오늘 사용량 조회 const today = new Date().toISOString().slice(0, 10) const { data: usage } = await serviceRoleClient .from('daily_usage') .select('count') .eq('user_id', userId) .eq('date', today) .eq('feature', feature) .maybeSingle() const current = (usage?.count as number) ?? 0 return { allowed: current < limit, current, limit, tier } } /** * 쿼터 소비. increment_daily_usage 함수 호출 (service_role 전용). */ export async function consumeQuota( userId: string, feature: Feature, serviceRoleClient: ReturnType, amount: number = 1 ): Promise { const { data, error } = await serviceRoleClient.rpc('increment_daily_usage', { p_user_id: userId, p_feature: feature, p_amount: amount }) if (error) { throw new Error(`Failed to increment quota: ${error.message}`) } return (data as number) ?? 0 } /** * service role 클라이언트 생성 헬퍼 */ export function createServiceRoleClient(): ReturnType { // @ts-expect-error — Deno.env는 Deno 런타임 전역 const url = Deno.env.get('SUPABASE_URL') ?? '' // @ts-expect-error — Deno.env는 Deno 런타임 전역 const serviceKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? '' return createClient(url, serviceKey, { auth: { persistSession: false, autoRefreshToken: false } }) }