import { corsHeaders, handleCorsPreflightRequest } from '../_shared/cors.ts' import { requireUser, authErrorResponse, type AuthError } from '../_shared/auth.ts' import { createBillingCatalog, parseStripeCatalogPrice, type BillingCatalogPrice, type BillingCatalogTier, } from '../_shared/billing-catalog.ts' import { getPaypleConfig, PaypleConfigurationError, TIER_PRICE, } from '../_shared/payple.ts' const NO_STORE_HEADERS = { ...corsHeaders, 'Content-Type': 'application/json', 'Cache-Control': 'no-store', 'X-Content-Type-Options': 'nosniff', } function jsonResponse(body: unknown, status = 200): Response { return new Response(JSON.stringify(body), { status, headers: NO_STORE_HEADERS }) } async function loadStripePrice( secretKey: string, priceId: string, ): Promise | null> { const response = await fetch(`https://api.stripe.com/v1/prices/${encodeURIComponent(priceId)}`, { method: 'GET', headers: { Authorization: `Bearer ${secretKey}` }, signal: AbortSignal.timeout(8_000), }) if (!response.ok) return null const payload = await response.json().catch(() => null) return parseStripeCatalogPrice(payload, priceId) } Deno.serve(async (req: Request) => { const preflight = handleCorsPreflightRequest(req) if (preflight) return preflight if (req.method !== 'POST') return jsonResponse({ error: 'method_not_allowed' }, 405) try { await requireUser(req) let payple: Record | null = null try { getPaypleConfig() payple = { pro: TIER_PRICE.pro, pro_plus: TIER_PRICE.pro_plus, } } catch (error) { if (!(error instanceof PaypleConfigurationError)) throw error } const stripeSecret = Deno.env.get('STRIPE_SECRET_KEY')?.trim() ?? '' const stripeIds: Record = { pro: Deno.env.get('STRIPE_PRICE_PRO')?.trim() ?? '', pro_plus: (Deno.env.get('STRIPE_PRICE_PRO_PLUS') ?? Deno.env.get('STRIPE_PRICE_TEAM'))?.trim() ?? '', } const stripe: Partial>> = {} if (stripeSecret) { const tiers: BillingCatalogTier[] = ['pro', 'pro_plus'] await Promise.all(tiers.map(async (tier) => { const priceId = stripeIds[tier] if (!priceId) return const price = await loadStripePrice(stripeSecret, priceId).catch(() => null) if (price) stripe[tier] = price })) } return jsonResponse(createBillingCatalog({ payple, stripe })) } catch (error) { if (error && typeof error === 'object' && 'status' in error && 'message' in error) { return authErrorResponse(error as AuthError, NO_STORE_HEADERS) } return jsonResponse({ error: 'billing_catalog_unavailable' }, 503) } })