UNPKG

spaps-sdk

Version:

Sweet Potato Authentication & Payment Service SDK - Zero-config client with built-in permission checking and role-based access control

451 lines (445 loc) 17.2 kB
import * as spaps_types from 'spaps-types'; import { CreateProductRequest, Product, UpdateProductRequest, CreatePriceRequest, Price, ProductSyncResult, CryptoReconcileRequest, CreateSecureMessageRequest, SecureMessage, AuthResponse, User as User$1, CreateCryptoInvoiceRequest, CryptoInvoiceStatusSnapshot, CheckoutSession, Subscription, UsageBalance, VerifyCryptoWebhookSignatureOptions } from 'spaps-types'; export { AdminPermission, AdminRole, AdminUser, ApiResponse, AuthResponse, CheckoutSession, CreateCryptoInvoiceRequest, CreatePriceRequest, CreateProductRequest, CreateSecureMessageInput, CreateSecureMessageRequest, CryptoInvoice, CryptoInvoiceResponse, CryptoInvoiceStatusSnapshot, CryptoReconcileRequest, Price, Product, ProductSyncResult, SecureMessage, SecureMessageOutput, Subscription, TokenPair, UpdateProductRequest, UsageBalance, User, UserProfile, UserRole, UserWallet, VerifyCryptoWebhookSignatureOptions, createSecureMessageRequestSchema, secureMessageMetadataSchema, secureMessageSchema } from 'spaps-types'; /** * Permission checking utilities for SPAPS SDK * Client-side role and permission management */ interface User { id: string; email?: string; wallet_address?: string; role?: string; permissions?: string[]; tier?: string; } interface AdminConfig { email: string; wallets: { ethereum: string; solana: string; }; } interface PermissionCheckResult { allowed: boolean; reason?: string; userRole: string; requiredRole?: string; } declare const DEFAULT_ADMIN_ACCOUNTS: AdminConfig; /** * Check if an identifier (email/wallet) is an admin account */ declare function isAdminAccount(identifier: string, customAdmins?: (string | AdminConfig)[]): boolean; /** * Get user role based on identifier */ declare function getUserRole(identifier?: string, customAdmins?: (string | AdminConfig)[]): string; /** * Check if user has specific permissions */ declare function hasPermission(user: User | null, requiredPermissions: string | string[], customAdmins?: (string | AdminConfig)[]): boolean; /** * Check if user can access admin features */ declare function canAccessAdmin(user: User | null, customAdmins?: (string | AdminConfig)[]): PermissionCheckResult; /** * Get role-aware error message */ declare function getRoleAwareErrorMessage(requiredRole: string, userRole: string, action?: string): string; /** * Get user display information with role indicators */ declare function getUserDisplay(user: User | null, customAdmins?: (string | AdminConfig)[]): { displayName: string; role: string; badge: string | null; isAdmin: boolean; }; /** * Permission checker class for easier usage */ declare class PermissionChecker { private customAdmins; constructor(customAdmins?: (string | AdminConfig)[]); isAdmin(identifier: string): boolean; getRole(identifier?: string): string; hasPermission(user: User | null, permissions: string | string[]): boolean; canAccessAdmin(user: User | null): PermissionCheckResult; getErrorMessage(requiredRole: string, userRole: string, action?: string): string; getUserDisplay(user: User | null): { displayName: string; role: string; badge: string | null; isAdmin: boolean; }; requiresAuth(user: User | null): boolean; requiresAdmin(user: User | null): boolean; addCustomAdmin(admin: string | AdminConfig): void; removeCustomAdmin(admin: string | AdminConfig): void; } /** * Create a permission checker instance */ declare function createPermissionChecker(customAdmins?: (string | AdminConfig)[]): PermissionChecker; declare const defaultPermissionChecker: PermissionChecker; interface SPAPSConfig { apiUrl?: string; apiKey?: string; autoDetect?: boolean; timeout?: number; } declare class SPAPSClient<SecureMessageMetadata extends Record<string, any> = Record<string, any>> { private client; private apiKey?; private accessToken?; private refreshToken?; private _isLocalMode; private unwrapApiResponse; private isAxiosResponse; private isResponseLikeWithData; private isApiResponse; admin: { createProduct: (productData: CreateProductRequest) => Promise<{ data: Product; }>; updateProduct: (productId: string, updates: UpdateProductRequest) => Promise<{ data: Product; }>; deleteProduct: (productId: string) => Promise<{ data: { id: string; active: boolean; archived: boolean; }; }>; createPrice: (priceData: CreatePriceRequest) => Promise<{ data: Price; }>; syncProducts: () => Promise<{ data: ProductSyncResult; }>; getProducts: () => Promise<{ data: { products: Product[]; total: number; adminMetadata?: any; }; }>; triggerCryptoReconcile: (opts?: CryptoReconcileRequest) => Promise<{ job_id: string; scheduled_at: string; cursor?: Record<string, unknown>; }>; }; secureMessages: { create: (payload: CreateSecureMessageRequest<SecureMessageMetadata>) => Promise<SecureMessage<SecureMessageMetadata>>; list: () => Promise<SecureMessage<SecureMessageMetadata>[]>; }; constructor(config?: SPAPSConfig); /** Raw API request helper that returns an ApiResponse-like shape */ request<T = any>(method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH', url: string, data?: any, requiresAuth?: boolean): Promise<{ success: boolean; data?: T; error?: { code: string; message: string; details?: any; }; }>; /** Health check helper that returns boolean */ healthCheck(): Promise<boolean>; login(email: string, password: string): Promise<{ data: AuthResponse; }>; register(email: string, password: string): Promise<{ data: AuthResponse; }>; walletSignIn(walletAddress: string, signature: string, message: string, chainType?: 'solana' | 'ethereum'): Promise<{ data: AuthResponse; }>; refresh(refreshToken?: string): Promise<{ data: AuthResponse; }>; logout(): Promise<void>; getUser(): Promise<{ data: User$1; }>; auth: { /** * Verify magic link token without mutating token state. * Returns a simple success object from the API. */ getNonce: (walletAddress: string) => Promise<any>; signInWithWallet: (req: { wallet_address: string; signature: string; message: string; chain_type?: "solana" | "ethereum" | "bitcoin" | "base"; username?: string; }) => Promise<any>; authenticateWallet: (walletAddress: string, signFn: (message: string) => Promise<string> | string, chainType?: "solana" | "ethereum" | "bitcoin" | "base", username?: string) => Promise<any>; signInWithPassword: (payload: { email: string; password: string; }) => Promise<any>; requestMagicLink: (payload: { email: string; redirect_url?: string; }) => Promise<void>; requestPasswordReset: (payload: { email: string; redirect_url?: string; }) => Promise<void>; confirmPasswordReset: (payload: { token: string; new_password: string; }) => Promise<void>; register: (payload: { email: string; password: string; }) => Promise<any>; /** * Verify a magic link token. Does not set access/refresh tokens. * Consumers should redirect or prompt login based on the returned status. */ verifyMagicLink: (payload: { token: string; }) => Promise<{ success: boolean; }>; solana: { linkWallet: (payload: { wallet_address: string; signature: string; message: string; }) => Promise<any>; verifySignature: (payload: { wallet_address: string; signature: string; message: string; }) => Promise<any>; generateMessage: (wallet_address: string) => Promise<any>; getWallets: () => Promise<any>; networkInfo: () => Promise<any>; }; ethereum: { linkWallet: (payload: { wallet_address: string; signature: string; message: string; }) => Promise<any>; verifySignature: (payload: { wallet_address: string; signature: string; message: string; }) => Promise<any>; verifyTypedData: (payload: { wallet_address: string; signature: string; typed_data: any; }) => Promise<any>; generateMessage: (wallet_address: string) => Promise<any>; generateTypedData: (wallet_address: string) => Promise<any>; getWallets: () => Promise<any>; networkInfo: () => Promise<any>; balance: (wallet_address: string) => Promise<any>; contractCheck: (wallet_address: string, contract_address: string) => Promise<any>; }; refreshToken: (refreshToken: string) => Promise<any>; /** * Logout and clear tokens. Network errors are intentionally swallowed * to avoid trapping users in a bad state during sign‑out flows. */ logout: () => Promise<void>; getCurrentUser: () => Promise<User$1>; isAuthenticated: () => boolean; }; payments: { crypto: { createInvoice: (payload: CreateCryptoInvoiceRequest) => Promise<spaps_types.CryptoInvoice>; getInvoice: (invoiceId: string) => Promise<spaps_types.CryptoInvoice>; getInvoiceStatus: (invoiceId: string) => Promise<CryptoInvoiceStatusSnapshot>; reconcile: (options?: CryptoReconcileRequest) => Promise<{ job_id: string; scheduled_at: string; cursor?: Record<string, unknown>; }>; }; createCheckoutSession: (payload: any) => Promise<CheckoutSession>; createPaymentCheckout: (params: { price_id: string; quantity?: number; success_url: string; cancel_url: string; }) => Promise<CheckoutSession>; createSubscriptionCheckout: (params: { price_id: string; success_url: string; cancel_url: string; trial_period_days?: number; }) => Promise<CheckoutSession>; getCheckoutSession: (sessionId: string) => Promise<CheckoutSession>; listCheckoutSessions: (query?: { limit?: number; starting_after?: string; }) => Promise<{ sessions: any[]; has_more: boolean; next_cursor?: string; }>; expireCheckoutSession: (sessionId: string) => Promise<{ id: string; status: string; expired: boolean; }>; listProducts: (query?: { category?: string; active?: boolean; limit?: number; starting_after?: string; }) => Promise<{ products: Product[]; total: number; adminMetadata?: any; }>; getProduct: (productId: string) => Promise<Product>; createCustomerPortalSession: (payload: { return_url: string; }) => Promise<{ id: string; url: string; }>; createGuestCheckoutSession: (payload: any) => Promise<any>; getGuestCheckoutSession: (sessionId: string) => Promise<any>; listGuestCheckoutSessions: (query?: { limit?: number; starting_after?: string; }) => Promise<any>; convertGuestCheckoutSession: (payload: { session_id: string; }) => Promise<any>; convertGuestCheckout: (payload: { session_id: string; }) => Promise<any>; listAllProductsSuperAdmin: () => Promise<any>; updateProductSuperAdmin: (productId: string, updates: any) => Promise<any>; deleteProductSuperAdmin: (productId: string) => Promise<any>; createProductWithPrice: (payload: any) => Promise<any>; createProductWithPriceSuperAdmin: (productId: string, payload: any) => Promise<any>; setDefaultPrice: (productId: string, payload: { price_id: string; }) => Promise<any>; setDefaultPriceSuperAdmin: (productId: string, payload: { price_id: string; }) => Promise<any>; createDefaultNewPrice: (productId: string, payload: any) => Promise<any>; superAdminListAllProducts: () => Promise<any>; superAdminUpdateProduct: (productId: string, updates: any) => Promise<any>; superAdminArchiveProduct: (productId: string) => Promise<any>; superAdminCreateProductWithPrice: (applicationId: string, payload: any) => Promise<any>; superAdminCreatePriceAndSetDefault: (productId: string, payload: any) => Promise<any>; superAdminSetDefaultPrice: (productId: string, payload: { price_id: string; }) => Promise<any>; }; sessions: { getCurrent: () => Promise<any>; list: (params?: { limit?: number; starting_after?: string; }) => Promise<any>; validate: () => Promise<any>; revoke: (sessionId: string) => Promise<any>; revokeAll: () => Promise<any>; touch: () => Promise<any>; }; createCheckoutSession(priceId: string, successUrl: string, cancelUrl?: string): Promise<{ data: CheckoutSession; }>; getSubscription(): Promise<{ data: Subscription; }>; cancelSubscription(): Promise<void>; getUsageBalance(): Promise<{ data: UsageBalance; }>; recordUsage(feature: string, amount: number): Promise<void>; private createSecureMessage; private listSecureMessages; /** * Create a new Stripe product (Admin required) */ createProduct(productData: CreateProductRequest): Promise<{ data: Product; }>; /** * Update an existing Stripe product (Admin required) */ updateProduct(productId: string, updates: UpdateProductRequest): Promise<{ data: Product; }>; /** * Archive (soft delete) a Stripe product (Admin required) */ deleteProduct(productId: string): Promise<{ data: { id: string; active: boolean; archived: boolean; }; }>; /** * Create a new price for a product (Admin required) */ createPrice(priceData: CreatePriceRequest): Promise<{ data: Price; }>; /** * Sync all products from Stripe to local database (Super Admin required) */ syncProducts(): Promise<{ data: ProductSyncResult; }>; /** * Get products with admin metadata (if user is admin) */ getProducts(): Promise<{ data: { products: Product[]; total: number; adminMetadata?: any; }; }>; isAuthenticated(): boolean; getAccessToken(): string | undefined; setAccessToken(token: string): void; isLocalMode(): boolean; /** * Check if current user has admin privileges * Note: This requires the user object from authentication */ isAdmin(user?: User$1): boolean; health(): Promise<{ data: any; }>; } declare function verifyCryptoWebhookSignature(options: VerifyCryptoWebhookSignatureOptions): boolean; declare class TokenManager { private static readonly ACCESS_TOKEN_KEY; private static readonly REFRESH_TOKEN_KEY; private static readonly USER_KEY; private static getStorage; static storeTokens(tokens: AuthResponse): void; static getAccessToken(): string | null; static getRefreshToken(): string | null; static getStoredUser(): User$1 | null; static clearTokens(): void; static isTokenExpired(token: string): boolean; static autoRefreshToken(sdk: SPAPSClient): Promise<boolean>; } declare class WalletUtils { static detectChainType(address: string): 'solana' | 'ethereum' | 'bitcoin' | null; static isValidAddress(address: string, chainType?: 'solana' | 'ethereum' | 'bitcoin' | 'base'): boolean; } export { type AdminConfig, DEFAULT_ADMIN_ACCOUNTS, type PermissionCheckResult, PermissionChecker, SPAPSClient as SPAPS, SPAPSClient, type SPAPSConfig, TokenManager, WalletUtils, canAccessAdmin, createPermissionChecker, SPAPSClient as default, defaultPermissionChecker, getRoleAwareErrorMessage, getUserDisplay, getUserRole, hasPermission, isAdminAccount, verifyCryptoWebhookSignature };