/** * Billing / Subscription client — thin wrapper over @bytelyst/subscription-client. * * Delegates subscription operations to the shared package. * Keeps ChronoMind-specific usage API as a local fetch call. * Client-side only — uses the stored auth token for authorization. */ import { createSubscriptionClient } from '@bytelyst/subscription-client'; import type { SubscriptionDoc } from '@bytelyst/subscription-client'; import { PRODUCT_ID, getBaseUrl, getAuthClient } from './auth-api'; // ── Shared client ────────────────────────────────────────────────── let _client: ReturnType | null = null; function getClient() { if (!_client) { _client = createSubscriptionClient({ baseUrl: `${getBaseUrl()}/api`, productId: PRODUCT_ID, userId: 'me', getAccessToken: () => getAuthClient().getAccessToken() ?? '', }); } return _client; } // ── Types (backwards-compatible) ─────────────────────────────────── export interface Subscription { id: string; productId: string; userId: string; plan: 'free' | 'pro'; status: 'active' | 'cancelled' | 'past_due' | 'trialing'; currentPeriodStart: string; currentPeriodEnd: string; cancelAtPeriodEnd: boolean; stripeCustomerId?: string; stripeSubscriptionId?: string; createdAt: string; updatedAt: string; } function toSubscription(doc: SubscriptionDoc): Subscription { return { id: doc.id, productId: doc.productId ?? PRODUCT_ID, userId: doc.userId, plan: doc.plan as Subscription['plan'], status: doc.status as Subscription['status'], currentPeriodStart: doc.currentPeriodStart, currentPeriodEnd: doc.currentPeriodEnd, cancelAtPeriodEnd: doc.cancelAtPeriodEnd, stripeCustomerId: doc.stripeCustomerId, stripeSubscriptionId: doc.stripeSubscriptionId, createdAt: doc.createdAt, updatedAt: doc.updatedAt, }; } // ── Subscription API ─────────────────────────────────────────────── export async function getMySubscription(_userId?: string): Promise { try { const doc = await getClient().getMySubscription(); return doc ? toSubscription(doc) : null; } catch { return null; } } export async function cancelSubscription(_userId?: string): Promise { try { const doc = await getClient().cancelSubscription(); return toSubscription(doc); } catch { return null; } } // ── Usage API (ChronoMind-specific, not in shared client) ────────── export interface UsageSummary { timersCreated: number; routinesCompleted: number; focusMinutes: number; } export async function getUsageSummary(userId: string, days = 30): Promise { try { const token = getAuthClient().getAccessToken(); const res = await fetch(`${getBaseUrl()}/usage/summary?userId=${userId}&days=${days}`, { headers: { 'Content-Type': 'application/json', 'x-product-id': PRODUCT_ID, ...(token ? { Authorization: `Bearer ${token}` } : {}), }, }); if (!res.ok) return null; const data = await res.json() as { summary: UsageSummary }; return data.summary; } catch { return null; } }