import { C as CreditSource, J as JournalReferenceType, a as CreditOperationType, P as PortableTransaction, A as AIProviderType, S as SubscriptionTier, b as PortableUserCredits, c as PortableReservation, R as ReservationStatus, d as PortableUsageLog, M as MonthlyResetResult, e as SubscriptionExpiryResult, f as PortableJournalEntry } from './types-DgQtamEe.cjs'; /** * Input for creating a credit reservation */ interface CreateReservationInput { userId: string; amount: number; operationType: CreditOperationType; expiresAt: Date; } /** * Input for creating a credit transaction */ interface CreateTransactionInput { userId: string; type: PortableTransaction["type"]; amount: number; description: string; paymentRef?: string; previousBalance: number; newBalance: number; } /** * Input for logging usage */ interface CreateUsageLogInput { userId: string; operationType: CreditOperationType; provider: AIProviderType; creditsUsed: number; success: boolean; errorMessage?: string; resourceId?: string; resourceType?: string; requestId?: string; metadata?: Record; } /** * Query options for usage logs */ interface UsageLogQuery { userId?: string; operationType?: CreditOperationType; success?: boolean; limit?: number; offset?: number; startDate?: Date; endDate?: Date; } /** * Input for creating a journal entry */ interface CreateJournalEntryInput { userId: string; entryType: "debit" | "credit"; amount: number; balanceAfter: number; source: CreditSource; referenceId: string; referenceType: JournalReferenceType; description: string; metadata?: Record; } /** * Query options for journal entries */ interface JournalEntryQuery { userId: string; source?: CreditSource; referenceType?: JournalReferenceType; limit?: number; offset?: number; startDate?: Date; endDate?: Date; } /** * Partial update for user credits balance */ interface CreditBalanceUpdate { balance?: number; bonusCredits?: number; reserved?: number; tier?: SubscriptionTier; monthlyLimit?: number; monthlyUsed?: number; monthlyResetAt?: Date | string; subscriptionExpiresAt?: Date | string | null; /** Increment balance by this amount (alternative to absolute value) */ balanceIncrement?: number; /** Increment bonusCredits by this amount (alternative to absolute value) */ bonusCreditsIncrement?: number; /** Increment reserved by this amount (alternative to absolute value) */ reservedIncrement?: number; /** Increment monthlyUsed by this amount */ monthlyUsedIncrement?: number; } /** * Input for tier update */ interface TierUpdateInput { tier: SubscriptionTier; monthlyLimit: number; balance?: number; monthlyUsed?: number; subscriptionExpiresAt?: Date | string | null; } /** * Repository interface for credits database operations * * Implementations can use any database (Firestore, PostgreSQL, etc.) * All methods should handle their own error handling and transactions */ interface ICreditRepository { /** * Get user credits balance * @param userId - User ID * @returns User credits or null if not found */ getUserCredits(userId: string): Promise; /** * Initialize credits for a new user * @param userId - User ID * @param tier - Initial subscription tier * @param initialBalance - Initial credit balance * @returns Initialized user credits */ initializeUserCredits(userId: string, tier: SubscriptionTier, initialBalance: number): Promise; /** * Update user credits balance * @param userId - User ID * @param updates - Partial updates to apply */ updateUserCredits(userId: string, updates: CreditBalanceUpdate): Promise; /** * Update user subscription tier * @param userId - User ID * @param input - Tier update data */ updateUserTier(userId: string, input: TierUpdateInput): Promise; /** * Create a credit reservation (phase 1 of two-phase commit) * @param input - Reservation data * @returns Created reservation */ createReservation(input: CreateReservationInput): Promise; /** * Get a reservation by ID * @param userId - User ID * @param reservationId - Reservation ID * @returns Reservation or null */ getReservation(userId: string, reservationId: string): Promise; /** * Update reservation status * @param userId - User ID * @param reservationId - Reservation ID * @param status - New status * @param completedAt - Completion timestamp */ updateReservationStatus(userId: string, reservationId: string, status: ReservationStatus, completedAt?: Date): Promise; /** * Reserve credits atomically (creates reservation + updates balance in transaction) * @param userId - User ID * @param amount - Credits to reserve * @param operationType - Operation type for tracking * @param expiresAt - Reservation expiry time * @returns Created reservation * @throws Error if insufficient credits */ reserveCreditsAtomic(userId: string, amount: number, operationType: CreditOperationType, expiresAt: Date): Promise; /** * Commit a reservation atomically (deducts credits + marks reservation committed) * @param userId - User ID * @param reservationId - Reservation ID * @throws Error if reservation not found or not in reserved state */ commitReservationAtomic(userId: string, reservationId: string): Promise; /** * Release a reservation atomically (releases reserved credits + marks reservation released) * @param userId - User ID * @param reservationId - Reservation ID */ releaseReservationAtomic(userId: string, reservationId: string): Promise; /** * Add credits atomically (creates transaction + updates balance) * @param userId - User ID * @param amount - Credits to add * @param description - Transaction description * @param paymentRef - Optional payment reference */ addCreditsAtomic(userId: string, amount: number, description: string, paymentRef?: string): Promise; /** * Deduct credits from a user's balance atomically. * * Splits the deduction across `balance` and `bonusCredits`, draining * `balance` (monthly, resets each cycle) first so persistent bonus * credits survive longer. Runs in a single atomic transaction so * concurrent deducts cannot drive either field negative. * * Callers are responsible for writing any audit record (journal / * transaction) — this method only moves credits. * * @param userId - User ID * @param amount - Credits to deduct (positive) * @returns Combined totals (balance + bonusCredits) before and after. * @throws If user has no credits doc or insufficient credits */ deductCreditsAtomic(userId: string, amount: number): Promise<{ previousBalance: number; newBalance: number; }>; /** * Create a credit transaction record * @param input - Transaction data * @returns Created transaction */ createTransaction(input: CreateTransactionInput): Promise; /** * Get user's transaction history * @param userId - User ID * @param limit - Max results * @param offset - Skip results * @returns List of transactions */ getTransactions(userId: string, limit?: number, offset?: number): Promise; /** * Log a usage event * @param input - Usage log data * @returns Created usage log */ logUsage(input: CreateUsageLogInput): Promise; /** * Query usage logs * @param query - Query parameters * @returns List of usage logs */ getUsageLogs(query: UsageLogQuery): Promise; /** * Get usage log count (for pagination) * @param query - Query parameters (without limit/offset) * @returns Count of matching logs */ getUsageLogsCount(query: Omit): Promise; /** * Find and expire reservations past their expiration time * Used by cron job to clean up stale reservations * @param batchSize - Maximum number of reservations to process per batch (default: 100) * @param maxIterations - Maximum number of pagination iterations to prevent infinite loops (default: 100) * @returns Cleanup results with counts and errors */ findAndExpireReservations(batchSize?: number, maxIterations?: number): Promise<{ expiredCount: number; creditsReleased: number; errors: string[]; }>; /** * Atomically perform monthly reset if needed * Uses optimistic locking to prevent race conditions * * @param userId - User ID * @param tier - User's current subscription tier (for determining new balance) * @param expectedResetAt - The expected monthlyResetAt value (for optimistic locking) * @returns Result indicating whether reset was performed and updated credits */ atomicMonthlyReset(userId: string, tier: SubscriptionTier, expectedResetAt: Date | string): Promise; /** * Check and handle subscription expiry with grace period * Auto-downgrades expired subscriptions after grace period * * @param userId - User ID * @param gracePeriodDays - Days to allow after expiry before downgrade (default: 3) * @returns Result indicating whether downgrade occurred */ checkAndHandleSubscriptionExpiry(userId: string, gracePeriodDays?: number): Promise; /** * Create a journal entry for audit trail * @param input - Journal entry data * @returns Created journal entry */ createJournalEntry(input: CreateJournalEntryInput): Promise; /** * Get journal entries for a user * @param query - Query parameters * @returns List of journal entries */ getJournalEntries(query: JournalEntryQuery): Promise; /** * Get journal entry count for pagination * @param query - Query parameters (without limit/offset) * @returns Count of matching entries */ getJournalEntriesCount(query: Omit): Promise; } /** * Factory type for creating repository instances */ type CreditRepositoryFactory = () => ICreditRepository; /** * Convert PortableUserCredits to client-safe format * Utility function that implementations can use */ declare function toClientUserCredits(credits: PortableUserCredits): PortableUserCredits; export { type CreateJournalEntryInput as C, type ICreditRepository as I, type JournalEntryQuery as J, type TierUpdateInput as T, type UsageLogQuery as U, type CreateReservationInput as a, type CreateTransactionInput as b, type CreateUsageLogInput as c, type CreditBalanceUpdate as d, type CreditRepositoryFactory as e, toClientUserCredits as t };