import 'reflect-metadata' import { expoClient } from '@better-auth/expo/client' import { createSkerClientPlugin } from '@repo/sdk' import { adminClient, emailOTPClient, genericOAuthClient, jwtClient, organizationClient, phoneNumberClient, usernameClient, } from 'better-auth/client/plugins' import { createAuthClient } from 'better-auth/react' import { fetchWithLogger } from './fetch-logger' import type { Subscription } from './plugins/stripe' import { stripeClient } from './plugins/stripe-plugin' import { storage } from './storage' import type { ApiError } from './types' const OWNER_ID = process.env.EXPO_PUBLIC_OWNER_ID export interface CreditBalance { tokenUsage: number remainingTokenBalance: number currentCreditBalance: number unitPrice: number } export interface SubscriptionListItem extends Subscription { type?: 'metered' | 'licenced' limits?: Record creditBalance?: CreditBalance highestTierPlan?: string highestTierCredits?: number } export interface SubscriptionListParams { query?: { referenceId?: string } } export interface SubscriptionRestoreParams { referenceId?: string subscriptionId?: string } export interface SubscriptionRestoreResponse { success: boolean subscription: { id: string stripeSubscriptionId: string cancelAtPeriodEnd: boolean periodEnd?: Date status: string } } export interface BillingPortalParams { locale?: string referenceId?: string returnUrl?: string } export interface BillingPortalResponse { url: string redirect: boolean } export interface ISubscription { list: (params?: SubscriptionListParams) => Promise<{ data?: SubscriptionListItem[]; error?: ApiError }> restore: (params?: SubscriptionRestoreParams) => Promise<{ data?: SubscriptionRestoreResponse; error?: ApiError }> billingPortal: (params?: BillingPortalParams) => Promise<{ data?: BillingPortalResponse; error?: ApiError }> } export const getAuthToken = async () => (await storage.getItem('bestaibest.better-auth.session_token')) || '' export const setAuthToken = async (token: string) => { await storage.setItem(`bestaibest.better-auth.session_token`, token) } export const authClient = createAuthClient({ baseURL: 'https://api.mixvideo.bowong.cc', trustedOrigins: ['duooomi://', 'https://api.mixvideo.bowong.cc'], storage, scheme: 'duooomi', fetchOptions: { headers: { 'x-ownerid': OWNER_ID, }, auth: { type: 'Bearer', token: async () => { const Authorization = await getAuthToken() return Authorization }, }, customFetchImpl: fetchWithLogger as typeof fetch, }, plugins: [ createSkerClientPlugin(), stripeClient(), usernameClient(), phoneNumberClient(), emailOTPClient(), genericOAuthClient(), jwtClient(), adminClient(), organizationClient(), expoClient({ storage: storage as any, }), ], }) export const { signIn, signUp, signOut, useSession, $Infer, admin, forgetPassword, resetPassword, emailOtp } = authClient export const subscription: ISubscription = Reflect.get(authClient, 'subscription')