All files / web/src/lib stripe.ts

0% Statements 0/63
0% Branches 0/1
0% Functions 0/1
0% Lines 0/63

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64                                                                                                                               
import Stripe from 'stripe'
import { eq } from 'drizzle-orm'
import { db } from '@/db'
import { appSettings, type PricingConfig } from '@/db/schema/app-settings'

let _stripe: Stripe | null = null

/** Lazily initialised Stripe client — avoids crashes at build time when env vars are absent. */
export function getStripe(): Stripe {
  if (!_stripe) {
    const key = process.env.STRIPE_SECRET_KEY
    if (!key) {
      throw new Error('[stripe] STRIPE_SECRET_KEY is not set')
    }
    _stripe = new Stripe(key, {
      apiVersion: '2026-01-28.clover',
      typescript: true,
    })
  }
  return _stripe
}

/** Price ID for the Family plan (monthly). Set in Stripe dashboard. */
export const FAMILY_MONTHLY_PRICE_ID = process.env.STRIPE_FAMILY_MONTHLY_PRICE_ID ?? ''

/** Price ID for the Family plan (annual). Set in Stripe dashboard. */
export const FAMILY_ANNUAL_PRICE_ID = process.env.STRIPE_FAMILY_ANNUAL_PRICE_ID ?? ''

/** Webhook signing secret. */
export const STRIPE_WEBHOOK_SECRET = process.env.STRIPE_WEBHOOK_SECRET ?? ''

/**
 * Get active price IDs and amounts, checking DB first then falling back to env vars.
 *
 * Returns the pricing config from app_settings if set, otherwise constructs
 * one from environment variables (amounts default to pricing.json values).
 */
export async function getActivePricing(): Promise<PricingConfig> {
  try {
    const [settings] = await db
      .select({ pricing: appSettings.pricing })
      .from(appSettings)
      .where(eq(appSettings.id, 'default'))
      .limit(1)

    if (settings?.pricing) {
      const parsed = JSON.parse(settings.pricing) as PricingConfig
      if (parsed.family?.monthly?.priceId && parsed.family?.annual?.priceId) {
        return parsed
      }
    }
  } catch {
    console.error('[stripe] Failed to read pricing from DB, falling back to env vars')
  }

  // Fall back to env vars
  return {
    family: {
      monthly: { amount: 600, priceId: FAMILY_MONTHLY_PRICE_ID },
      annual: { amount: 3768, priceId: FAMILY_ANNUAL_PRICE_ID },
    },
  }
}