All files / web/src/lib billing-sync.ts

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

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 65 66 67 68                                                                                                                                       
import { eq } from 'drizzle-orm'
import { db, schema } from '@/db'
import { getStripe } from './stripe'
import { createId } from '@paralleldrive/cuid2'

/**
 * Sync a completed checkout session into the local subscriptions table.
 *
 * Idempotent — safe to call from both the Stripe webhook and the
 * verify-on-redirect endpoint. If a subscription row already exists
 * for this user, it's updated; otherwise a new row is created.
 */
export async function syncCheckoutSession(sessionId: string) {
  const session = await getStripe().checkout.sessions.retrieve(sessionId)

  const userId = session.client_reference_id || session.metadata?.userId
  if (!userId || !session.subscription || !session.customer) return

  const stripeSubscriptionId =
    typeof session.subscription === 'string' ? session.subscription : session.subscription.id
  const stripeCustomerId =
    typeof session.customer === 'string' ? session.customer : session.customer.id

  // Fetch full subscription to get current_period_end
  const sub = await getStripe().subscriptions.retrieve(stripeSubscriptionId)
  const firstItem = sub.items.data[0]
  const currentPeriodEnd = firstItem?.current_period_end
    ? new Date(firstItem.current_period_end * 1000)
    : new Date()

  const now = new Date()
  const existing = await db
    .select({ id: schema.subscriptions.id })
    .from(schema.subscriptions)
    .where(eq(schema.subscriptions.userId, userId))
    .get()

  if (existing) {
    await db
      .update(schema.subscriptions)
      .set({
        stripeCustomerId,
        stripeSubscriptionId,
        plan: 'family',
        status: 'active',
        currentPeriodEnd,
        cancelAtPeriodEnd: false,
        updatedAt: now,
      })
      .where(eq(schema.subscriptions.userId, userId))
  } else {
    await db.insert(schema.subscriptions).values({
      id: createId(),
      userId,
      stripeCustomerId,
      stripeSubscriptionId,
      plan: 'family',
      status: 'active',
      currentPeriodEnd,
      cancelAtPeriodEnd: false,
      createdAt: now,
      updatedAt: now,
    })
  }

  console.log(`[billing-sync] synced checkout session: user=${userId} plan=family`)
}