UNPKG

@rohitkvs/revrag-web-sdk

Version:

Industry-standard React SDK for Revrag chat functionality with simple script integration. Zero setup required - just include a script tag!

1 lines 140 kB
{"version":3,"file":"revrag-sdk.es.mjs","sources":["../src/sdk/RevragSDK.ts","../src/types/index.ts","../src/core/errors/RevragError.ts","../src/core/events/EventEmitter.ts","../src/core/plugins/PluginManager.ts","../src/services/ApiService.ts","../node_modules/react/cjs/react-jsx-runtime.production.min.js","../node_modules/react/cjs/react-jsx-runtime.development.js","../node_modules/react/jsx-runtime.js","../src/components/RevragChat.tsx","../src/components/FloatingHelpWidget.tsx","../src/index.ts"],"sourcesContent":["export interface RevragConfig {\n apiKey: string;\n baseUrl?: string;\n debug?: boolean;\n}\n\nexport interface RevragMessage {\n id: string;\n content: string;\n timestamp: Date;\n type: 'user' | 'assistant';\n}\n\nexport interface RevragResponse {\n success: boolean;\n data?: unknown;\n error?: string;\n}\n\nexport class RevragSDK {\n private config: RevragConfig;\n private isInitialized: boolean = false;\n\n constructor(config: RevragConfig) {\n this.config = {\n baseUrl: 'https://api.revrag.com',\n debug: false,\n ...config\n };\n }\n\n /**\n * Initialize the SDK\n */\n async init(): Promise<void> {\n if (this.config.debug) {\n console.log('Initializing Revrag SDK...', this.config);\n }\n \n // Simulate API call to validate API key\n try {\n await this.validateApiKey();\n this.isInitialized = true;\n if (this.config.debug) {\n console.log('Revrag SDK initialized successfully');\n }\n } catch (error) {\n throw new Error(`Failed to initialize Revrag SDK: ${error}`);\n }\n }\n\n /**\n * Send a message and get response\n */\n async sendMessage(content: string): Promise<RevragResponse> {\n if (!this.isInitialized) {\n throw new Error('SDK not initialized. Call init() first.');\n }\n\n try {\n if (this.config.debug) {\n console.log('Sending message:', content);\n }\n\n // Simulate API call\n const response = await this.makeApiCall('/chat', {\n method: 'POST',\n body: JSON.stringify({ message: content })\n });\n\n return {\n success: true,\n data: response\n };\n } catch (error) {\n if (this.config.debug) {\n console.error('Error sending message:', error);\n }\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error'\n };\n }\n }\n\n /**\n * Get chat history\n */\n async getChatHistory(): Promise<RevragMessage[]> {\n if (!this.isInitialized) {\n throw new Error('SDK not initialized. Call init() first.');\n }\n\n // Simulate returning chat history\n return [\n {\n id: '1',\n content: 'Hello, how can I help you?',\n timestamp: new Date(),\n type: 'assistant'\n },\n {\n id: '2', \n content: 'I need help with my project',\n timestamp: new Date(),\n type: 'user'\n }\n ];\n }\n\n /**\n * Clear chat history\n */\n async clearHistory(): Promise<RevragResponse> {\n if (!this.isInitialized) {\n throw new Error('SDK not initialized. Call init() first.');\n }\n\n try {\n await this.makeApiCall('/chat/clear', { method: 'DELETE' });\n return { success: true };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error'\n };\n }\n }\n\n /**\n * Get SDK status\n */\n getStatus() {\n return {\n initialized: this.isInitialized,\n config: {\n baseUrl: this.config.baseUrl,\n debug: this.config.debug,\n hasApiKey: !!this.config.apiKey\n }\n };\n }\n\n private async validateApiKey(): Promise<void> {\n if (!this.config.apiKey) {\n throw new Error('API key is required');\n }\n\n // Simulate API key validation\n await new Promise(resolve => setTimeout(resolve, 500));\n \n if (this.config.apiKey === 'invalid') {\n throw new Error('Invalid API key');\n }\n }\n\n private async makeApiCall(endpoint: string, options: RequestInit): Promise<unknown> {\n const url = `${this.config.baseUrl}${endpoint}`;\n \n const response = await fetch(url, {\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.config.apiKey}`,\n ...options.headers\n }\n });\n\n if (!response.ok) {\n throw new Error(`API call failed: ${response.statusText}`);\n }\n\n return response.json();\n }\n}\n\n// Export a factory function for easier usage\nexport function createRevragSDK(config: RevragConfig): RevragSDK {\n return new RevragSDK(config);\n} ","/**\n * Core SDK Types and Interfaces\n * Following industry standards for React SDK architecture\n */\n\n// ============================================================================\n// Configuration Types\n// ============================================================================\n\nexport interface RevragConfig {\n apiKey: string;\n baseUrl?: string;\n debug?: boolean;\n timeout?: number;\n retryAttempts?: number;\n plugins?: RevragPlugin[];\n interceptors?: {\n request?: RequestInterceptor[];\n response?: ResponseInterceptor[];\n };\n cache?: CacheConfig;\n events?: EventConfig;\n}\n\nexport interface CacheConfig {\n enabled?: boolean;\n ttl?: number; // Time to live in milliseconds\n maxSize?: number;\n}\n\nexport interface EventConfig {\n enabled?: boolean;\n maxListeners?: number;\n}\n\n// ============================================================================\n// Core Data Types\n// ============================================================================\n\nexport interface RevragMessage {\n id: string;\n content: string;\n timestamp: Date;\n type: 'user' | 'assistant';\n metadata?: Record<string, unknown>;\n}\n\nexport interface RevragResponse<T = unknown> {\n success: boolean;\n data?: T;\n error?: RevragError;\n metadata?: {\n timestamp: Date;\n requestId: string;\n cached?: boolean;\n };\n}\n\nexport interface RevragChatResponse {\n message: RevragMessage;\n conversationId?: string;\n suggestions?: string[];\n}\n\n// ============================================================================\n// Error Types\n// ============================================================================\n\nexport interface RevragError {\n code: string;\n message: string;\n details?: Record<string, unknown>;\n stack?: string;\n}\n\nexport const RevragErrorCode = {\n INVALID_API_KEY: 'INVALID_API_KEY',\n NETWORK_ERROR: 'NETWORK_ERROR',\n TIMEOUT_ERROR: 'TIMEOUT_ERROR',\n RATE_LIMIT_ERROR: 'RATE_LIMIT_ERROR',\n VALIDATION_ERROR: 'VALIDATION_ERROR',\n SERVICE_UNAVAILABLE: 'SERVICE_UNAVAILABLE',\n UNKNOWN_ERROR: 'UNKNOWN_ERROR',\n} as const;\n\nexport type RevragErrorCode = typeof RevragErrorCode[keyof typeof RevragErrorCode];\n\n// ============================================================================\n// Plugin System Types\n// ============================================================================\n\nexport interface RevragPlugin {\n name: string;\n version: string;\n initialize?: (sdk: RevragSDKInterface) => Promise<void>;\n destroy?: () => Promise<void>;\n hooks?: {\n beforeRequest?: (config: RequestConfig) => RequestConfig | Promise<RequestConfig>;\n afterResponse?: (response: RevragResponse) => RevragResponse | Promise<RevragResponse>;\n onError?: (error: RevragError) => void | Promise<void>;\n onMessage?: (message: RevragMessage) => void | Promise<void>;\n };\n}\n\n// ============================================================================\n// Event Types\n// ============================================================================\n\nexport type EventMap = {\n 'message': [RevragMessage];\n 'error': [RevragError];\n 'connected': [];\n 'disconnected': [];\n 'initialized': [];\n 'destroyed': [];\n 'config:updated': [Partial<RevragConfig>];\n 'plugin:registered': [RevragPlugin];\n 'plugin:unregistered': [string];\n};\n\n// ============================================================================\n// Service Interfaces\n// ============================================================================\n\nexport interface ApiService {\n request<T = unknown>(endpoint: string, options?: RequestConfig): Promise<RevragResponse<T>>;\n get<T = unknown>(endpoint: string, config?: RequestConfig): Promise<RevragResponse<T>>;\n post<T = unknown>(endpoint: string, data?: unknown, config?: RequestConfig): Promise<RevragResponse<T>>;\n put<T = unknown>(endpoint: string, data?: unknown, config?: RequestConfig): Promise<RevragResponse<T>>;\n delete<T = unknown>(endpoint: string, config?: RequestConfig): Promise<RevragResponse<T>>;\n}\n\nexport interface CacheService {\n get<T = unknown>(key: string): Promise<T | null>;\n set<T = unknown>(key: string, value: T, ttl?: number): Promise<void>;\n delete(key: string): Promise<void>;\n clear(): Promise<void>;\n has(key: string): Promise<boolean>;\n}\n\nexport interface StorageService {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n clear(): void;\n}\n\nexport interface EventService {\n on<T extends keyof EventMap>(event: T, listener: (...args: EventMap[T]) => void): void;\n on(event: string, listener: (...args: unknown[]) => void): void;\n off<T extends keyof EventMap>(event: T, listener: (...args: EventMap[T]) => void): void;\n off(event: string, listener: (...args: unknown[]) => void): void;\n emit<T extends keyof EventMap>(event: T, ...args: EventMap[T]): void;\n emit(event: string, ...args: unknown[]): void;\n once<T extends keyof EventMap>(event: T, listener: (...args: EventMap[T]) => void): void;\n once(event: string, listener: (...args: unknown[]) => void): void;\n removeAllListeners(event?: string): void;\n}\n\n// ============================================================================\n// Request/Response Types\n// ============================================================================\n\nexport interface RequestConfig extends RequestInit {\n timeout?: number;\n retries?: number;\n metadata?: Record<string, unknown>;\n}\n\nexport type RequestInterceptor = (config: RequestConfig) => RequestConfig | Promise<RequestConfig>;\nexport type ResponseInterceptor = (response: RevragResponse) => RevragResponse | Promise<RevragResponse>;\n\n// ============================================================================\n// SDK Interface\n// ============================================================================\n\nexport interface RevragSDKInterface {\n // Core methods\n init(): Promise<void>;\n destroy(): Promise<void>;\n \n // Message methods\n sendMessage(content: string, options?: SendMessageOptions): Promise<RevragResponse<RevragChatResponse>>;\n getChatHistory(options?: GetHistoryOptions): Promise<RevragResponse<RevragMessage[]>>;\n clearHistory(): Promise<RevragResponse<void>>;\n \n // Configuration\n getConfig(): RevragConfig;\n updateConfig(config: Partial<RevragConfig>): Promise<void>;\n \n // Plugin management\n registerPlugin(plugin: RevragPlugin): Promise<void>;\n unregisterPlugin(name: string): Promise<void>;\n getPlugin(name: string): RevragPlugin | undefined;\n listPlugins(): RevragPlugin[];\n \n // Event system\n on<T extends keyof EventMap>(event: T, listener: (...args: EventMap[T]) => void): void;\n on(event: string, listener: (...args: unknown[]) => void): void;\n off<T extends keyof EventMap>(event: T, listener: (...args: EventMap[T]) => void): void;\n off(event: string, listener: (...args: unknown[]) => void): void;\n emit<T extends keyof EventMap>(event: T, ...args: EventMap[T]): void;\n emit(event: string, ...args: unknown[]): void;\n \n // Status\n getStatus(): SDKStatus;\n isInitialized(): boolean;\n}\n\nexport interface SendMessageOptions {\n conversationId?: string;\n metadata?: Record<string, unknown>;\n stream?: boolean;\n}\n\nexport interface GetHistoryOptions {\n conversationId?: string;\n limit?: number;\n offset?: number;\n filter?: {\n type?: 'user' | 'assistant';\n dateFrom?: Date;\n dateTo?: Date;\n };\n}\n\nexport interface SDKStatus {\n initialized: boolean;\n connected: boolean;\n config: {\n baseUrl: string;\n hasApiKey: boolean;\n debug: boolean;\n pluginsCount: number;\n };\n version: string;\n lastActivity?: Date;\n}\n\n// ============================================================================\n// React-specific Types\n// ============================================================================\n\nexport interface RevragChatProps {\n apiKey: string;\n config?: Partial<RevragConfig>;\n onMessage?: (message: RevragMessage) => void;\n onError?: (error: RevragError) => void;\n className?: string;\n theme?: 'light' | 'dark' | 'auto';\n}\n\nexport interface RevragProviderProps {\n children: React.ReactNode;\n config: RevragConfig;\n}\n\nexport interface UseRevragOptions {\n autoInit?: boolean;\n onMessage?: (message: RevragMessage) => void;\n onError?: (error: RevragError) => void;\n}\n\n// ============================================================================\n// Utility Types\n// ============================================================================\n\nexport type DeepPartial<T> = {\n [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];\n}; ","import { type RevragError as IRevragError, RevragErrorCode } from \"../../types\";\n\n/**\n * Custom Error class for Revrag SDK\n * Following industry standards for SDK error handling\n */\nexport class RevragError extends Error implements IRevragError {\n public readonly code: string;\n public readonly details?: Record<string, unknown>;\n public readonly timestamp: Date;\n public readonly requestId?: string;\n\n constructor(\n code: string,\n message: string,\n details?: Record<string, unknown>,\n requestId?: string\n ) {\n super(message);\n this.name = \"RevragError\";\n this.code = code;\n this.details = details;\n this.timestamp = new Date();\n this.requestId = requestId;\n\n // Maintain proper stack trace for where error was thrown (V8 only)\n const ErrorConstructor = Error as ErrorConstructor & {\n captureStackTrace?(targetObject: object, constructorOpt?: object): void;\n };\n if (ErrorConstructor.captureStackTrace) {\n ErrorConstructor.captureStackTrace(this, RevragError);\n }\n }\n\n /**\n * Convert error to JSON for serialization\n */\n toJSON(): IRevragError {\n return {\n code: this.code,\n message: this.message,\n details: this.details,\n stack: this.stack,\n };\n }\n\n /**\n * Check if error is of specific type\n */\n is(code: string): boolean {\n return this.code === code;\n }\n\n /**\n * Create error from unknown error\n */\n static fromError(\n error: unknown,\n code = RevragErrorCode.UNKNOWN_ERROR\n ): RevragError {\n if (error instanceof RevragError) {\n return error;\n }\n\n if (error instanceof Error) {\n return new RevragError(code, error.message, {\n originalError: error.message,\n });\n }\n\n return new RevragError(code, String(error));\n }\n\n /**\n * Factory methods for common error types\n */\n static invalidApiKey(message = \"Invalid API key provided\"): RevragError {\n return new RevragError(RevragErrorCode.INVALID_API_KEY, message);\n }\n\n static networkError(\n message = \"Network request failed\",\n details?: Record<string, unknown>\n ): RevragError {\n return new RevragError(RevragErrorCode.NETWORK_ERROR, message, details);\n }\n\n static timeoutError(\n message = \"Request timed out\",\n timeout?: number\n ): RevragError {\n return new RevragError(RevragErrorCode.TIMEOUT_ERROR, message, { timeout });\n }\n\n static rateLimitError(\n message = \"Rate limit exceeded\",\n retryAfter?: number\n ): RevragError {\n return new RevragError(RevragErrorCode.RATE_LIMIT_ERROR, message, {\n retryAfter,\n });\n }\n\n static validationError(message: string, field?: string): RevragError {\n return new RevragError(RevragErrorCode.VALIDATION_ERROR, message, {\n field,\n });\n }\n\n static serviceUnavailable(\n message = \"Service temporarily unavailable\"\n ): RevragError {\n return new RevragError(RevragErrorCode.SERVICE_UNAVAILABLE, message);\n }\n}\n","import { type EventService, type EventMap } from '../../types';\n\n/**\n * Type-safe Event Emitter for Revrag SDK\n * Following industry standards for SDK event systems\n */\nexport class RevragEventEmitter implements EventService {\n private regularListeners = new Map<string, Set<(...args: unknown[]) => void>>();\n private onceListeners = new Map<string, Set<(...args: unknown[]) => void>>();\n private maxListeners: number;\n\n constructor(maxListeners = 100) {\n this.maxListeners = maxListeners;\n }\n\n /**\n * Add event listener (typed version)\n */\n on<T extends keyof EventMap>(event: T, listener: (...args: EventMap[T]) => void): void;\n /**\n * Add event listener (generic version)\n */\n on(event: string, listener: (...args: unknown[]) => void): void;\n on(event: string, listener: (...args: unknown[]) => void): void {\n this.addListener(event, listener, false);\n }\n\n /**\n * Remove event listener (typed version)\n */\n off<T extends keyof EventMap>(event: T, listener: (...args: EventMap[T]) => void): void;\n /**\n * Remove event listener (generic version)\n */\n off(event: string, listener: (...args: unknown[]) => void): void;\n off(event: string, listener: (...args: unknown[]) => void): void {\n this.removeListener(event, listener);\n }\n\n /**\n * Emit event (typed version)\n */\n emit<T extends keyof EventMap>(event: T, ...args: EventMap[T]): void;\n /**\n * Emit event (generic version)\n */\n emit(event: string, ...args: unknown[]): void;\n emit(event: string, ...args: unknown[]): void {\n // Regular listeners\n const listeners = this.regularListeners.get(event);\n if (listeners && listeners.size > 0) {\n listeners.forEach(listener => {\n try {\n listener(...args);\n } catch (error) {\n // Emit error event to prevent uncaught exceptions\n setTimeout(() => {\n this.emit('error', error);\n }, 0);\n }\n });\n }\n\n // Once listeners\n const onceListeners = this.onceListeners.get(event);\n if (onceListeners && onceListeners.size > 0) {\n const listenersArray = Array.from(onceListeners);\n onceListeners.clear();\n \n listenersArray.forEach(listener => {\n try {\n listener(...args);\n } catch (error) {\n setTimeout(() => {\n this.emit('error', error);\n }, 0);\n }\n });\n }\n }\n\n /**\n * Add one-time event listener (typed version)\n */\n once<T extends keyof EventMap>(event: T, listener: (...args: EventMap[T]) => void): void;\n /**\n * Add one-time event listener (generic version)\n */\n once(event: string, listener: (...args: unknown[]) => void): void;\n once(event: string, listener: (...args: unknown[]) => void): void {\n this.addListener(event, listener, true);\n }\n\n /**\n * Remove all listeners for an event or all events\n */\n removeAllListeners(event?: string): void {\n if (event) {\n this.regularListeners.delete(event);\n this.onceListeners.delete(event);\n } else {\n this.regularListeners.clear();\n this.onceListeners.clear();\n }\n }\n\n /**\n * Get listener count for an event\n */\n listenerCount(event: string): number {\n const regularCount = this.regularListeners.get(event)?.size || 0;\n const onceCount = this.onceListeners.get(event)?.size || 0;\n return regularCount + onceCount;\n }\n\n /**\n * Get all event names that have listeners\n */\n eventNames(): string[] {\n const regularEvents = Array.from(this.regularListeners.keys());\n const onceEvents = Array.from(this.onceListeners.keys());\n return [...new Set([...regularEvents, ...onceEvents])];\n }\n\n /**\n * Get listeners for an event\n */\n listeners(event: string): ((...args: unknown[]) => void)[] {\n const regularListeners = Array.from(this.regularListeners.get(event) || []);\n const onceListeners = Array.from(this.onceListeners.get(event) || []);\n return [...regularListeners, ...onceListeners];\n }\n\n /**\n * Set maximum number of listeners per event\n */\n setMaxListeners(maxListeners: number): this {\n this.maxListeners = maxListeners;\n return this;\n }\n\n /**\n * Get maximum number of listeners per event\n */\n getMaxListeners(): number {\n return this.maxListeners;\n }\n\n /**\n * Private method to add listener with once support\n */\n private addListener(event: string, listener: (...args: unknown[]) => void, once: boolean): void {\n const targetMap = once ? this.onceListeners : this.regularListeners;\n \n if (!targetMap.has(event)) {\n targetMap.set(event, new Set());\n }\n\n const eventListeners = targetMap.get(event)!;\n \n // Check max listeners limit\n if (eventListeners.size >= this.maxListeners) {\n console.warn(\n `Warning: Possible EventEmitter memory leak detected. ` +\n `${eventListeners.size + 1} listeners added for event \"${event}\". ` +\n `Use setMaxListeners() to increase limit.`\n );\n }\n\n eventListeners.add(listener);\n }\n\n /**\n * Private method to remove listener\n */\n private removeListener(event: string, listener: (...args: unknown[]) => void): void {\n const regularListeners = this.regularListeners.get(event);\n if (regularListeners) {\n regularListeners.delete(listener);\n if (regularListeners.size === 0) {\n this.regularListeners.delete(event);\n }\n }\n\n const onceListeners = this.onceListeners.get(event);\n if (onceListeners) {\n onceListeners.delete(listener);\n if (onceListeners.size === 0) {\n this.onceListeners.delete(event);\n }\n }\n }\n} ","import { type RevragPlugin, type RevragSDKInterface } from '../../types';\nimport { RevragError } from '../errors/RevragError';\n\n/**\n * Plugin Manager for Revrag SDK\n * Following industry standards for extensible plugin architectures\n */\nexport class PluginManager {\n private plugins = new Map<string, RevragPlugin>();\n private sdk: RevragSDKInterface | null = null;\n\n /**\n * Set SDK reference for plugin initialization\n */\n setSdk(sdk: RevragSDKInterface): void {\n this.sdk = sdk;\n }\n\n /**\n * Register a plugin\n */\n async registerPlugin(plugin: RevragPlugin): Promise<void> {\n // Validate plugin structure\n this.validatePlugin(plugin);\n\n // Check for duplicate plugin names\n if (this.plugins.has(plugin.name)) {\n throw new RevragError(\n 'PLUGIN_ALREADY_EXISTS',\n `Plugin \"${plugin.name}\" is already registered`\n );\n }\n\n try {\n // Initialize plugin if it has an initialize method\n if (plugin.initialize && this.sdk) {\n await plugin.initialize(this.sdk);\n }\n\n // Store plugin\n this.plugins.set(plugin.name, plugin);\n\n // Emit plugin registered event\n if (this.sdk) {\n this.sdk.emit('plugin:registered', plugin);\n }\n\n } catch (error) {\n throw new RevragError(\n 'PLUGIN_INITIALIZATION_FAILED',\n `Failed to initialize plugin \"${plugin.name}\": ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Unregister a plugin\n */\n async unregisterPlugin(name: string): Promise<void> {\n const plugin = this.plugins.get(name);\n if (!plugin) {\n throw new RevragError(\n 'PLUGIN_NOT_FOUND',\n `Plugin \"${name}\" is not registered`\n );\n }\n\n try {\n // Call plugin destroy method if it exists\n if (plugin.destroy) {\n await plugin.destroy();\n }\n\n // Remove plugin\n this.plugins.delete(name);\n\n // Emit plugin unregistered event\n if (this.sdk) {\n this.sdk.emit('plugin:unregistered', name);\n }\n\n } catch (error) {\n throw new RevragError(\n 'PLUGIN_DESTRUCTION_FAILED',\n `Failed to destroy plugin \"${name}\": ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Get a plugin by name\n */\n getPlugin(name: string): RevragPlugin | undefined {\n return this.plugins.get(name);\n }\n\n /**\n * List all registered plugins\n */\n listPlugins(): RevragPlugin[] {\n return Array.from(this.plugins.values());\n }\n\n /**\n * Validate plugin structure\n */\n private validatePlugin(plugin: RevragPlugin): void {\n if (!plugin.name || typeof plugin.name !== 'string') {\n throw new RevragError('INVALID_PLUGIN', 'Plugin must have a valid name');\n }\n\n if (!plugin.version || typeof plugin.version !== 'string') {\n throw new RevragError('INVALID_PLUGIN', 'Plugin must have a valid version');\n }\n }\n}","import { \n type ApiService, \n type RevragConfig, \n type RevragResponse, \n type RequestConfig,\n type RequestInterceptor,\n type ResponseInterceptor,\n RevragErrorCode\n} from '../types';\nimport { RevragError } from '../core/errors/RevragError';\n\n/**\n * HTTP API Service with interceptors, retry logic, and proper error handling\n * Following industry standards from React SDKs like Stripe, Auth0, etc.\n */\nexport class RevragApiService implements ApiService {\n private baseUrl: string;\n private defaultHeaders: Record<string, string>;\n private timeout: number;\n private retryAttempts: number;\n private requestInterceptors: RequestInterceptor[] = [];\n private responseInterceptors: ResponseInterceptor[] = [];\n\n constructor(config: RevragConfig) {\n this.baseUrl = config.baseUrl || 'https://api.revrag.com';\n this.timeout = config.timeout || 30000;\n this.retryAttempts = config.retryAttempts || 3;\n \n this.defaultHeaders = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${config.apiKey}`,\n 'User-Agent': 'Revrag-SDK/1.0.0',\n };\n\n // Add interceptors from config\n if (config.interceptors?.request) {\n this.requestInterceptors.push(...config.interceptors.request);\n }\n if (config.interceptors?.response) {\n this.responseInterceptors.push(...config.interceptors.response);\n }\n }\n\n /**\n * Generic request method with full configuration\n */\n async request<T = unknown>(endpoint: string, options: RequestConfig = {}): Promise<RevragResponse<T>> {\n const url = this.buildUrl(endpoint);\n const requestId = this.generateRequestId();\n \n try {\n // Apply request interceptors\n const config = await this.applyRequestInterceptors({\n ...options,\n headers: {\n ...this.defaultHeaders,\n ...options.headers,\n },\n timeout: options.timeout || this.timeout,\n retries: options.retries || this.retryAttempts,\n metadata: {\n ...options.metadata,\n requestId,\n timestamp: new Date(),\n },\n });\n\n // Execute request with retry logic\n const response = await this.executeWithRetry<T>(url, config);\n \n // Apply response interceptors\n return await this.applyResponseInterceptors(response);\n \n } catch (error) {\n const revragError = RevragError.fromError(error);\n return {\n success: false,\n error: revragError.toJSON(),\n metadata: {\n timestamp: new Date(),\n requestId,\n },\n };\n }\n }\n\n /**\n * GET request\n */\n async get<T = unknown>(endpoint: string, config?: RequestConfig): Promise<RevragResponse<T>> {\n return this.request<T>(endpoint, {\n ...config,\n method: 'GET',\n });\n }\n\n /**\n * POST request\n */\n async post<T = unknown>(\n endpoint: string, \n data?: unknown, \n config?: RequestConfig\n ): Promise<RevragResponse<T>> {\n return this.request<T>(endpoint, {\n ...config,\n method: 'POST',\n body: data ? JSON.stringify(data) : undefined,\n });\n }\n\n /**\n * PUT request\n */\n async put<T = unknown>(\n endpoint: string, \n data?: unknown, \n config?: RequestConfig\n ): Promise<RevragResponse<T>> {\n return this.request<T>(endpoint, {\n ...config,\n method: 'PUT',\n body: data ? JSON.stringify(data) : undefined,\n });\n }\n\n /**\n * DELETE request\n */\n async delete<T = unknown>(endpoint: string, config?: RequestConfig): Promise<RevragResponse<T>> {\n return this.request<T>(endpoint, {\n ...config,\n method: 'DELETE',\n });\n }\n\n /**\n * Add request interceptor\n */\n addRequestInterceptor(interceptor: RequestInterceptor): void {\n this.requestInterceptors.push(interceptor);\n }\n\n /**\n * Add response interceptor\n */\n addResponseInterceptor(interceptor: ResponseInterceptor): void {\n this.responseInterceptors.push(interceptor);\n }\n\n /**\n * Remove request interceptor\n */\n removeRequestInterceptor(interceptor: RequestInterceptor): void {\n const index = this.requestInterceptors.indexOf(interceptor);\n if (index > -1) {\n this.requestInterceptors.splice(index, 1);\n }\n }\n\n /**\n * Remove response interceptor\n */\n removeResponseInterceptor(interceptor: ResponseInterceptor): void {\n const index = this.responseInterceptors.indexOf(interceptor);\n if (index > -1) {\n this.responseInterceptors.splice(index, 1);\n }\n }\n\n /**\n * Update configuration\n */\n updateConfig(config: Partial<RevragConfig>): void {\n if (config.baseUrl) {\n this.baseUrl = config.baseUrl;\n }\n if (config.timeout !== undefined) {\n this.timeout = config.timeout;\n }\n if (config.retryAttempts !== undefined) {\n this.retryAttempts = config.retryAttempts;\n }\n if (config.apiKey) {\n this.defaultHeaders['Authorization'] = `Bearer ${config.apiKey}`;\n }\n }\n\n /**\n * Private: Build full URL\n */\n private buildUrl(endpoint: string): string {\n if (endpoint.startsWith('http')) {\n return endpoint;\n }\n return `${this.baseUrl.replace(/\\/$/, '')}/${endpoint.replace(/^\\//, '')}`;\n }\n\n /**\n * Private: Generate unique request ID\n */\n private generateRequestId(): string {\n return `req_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n }\n\n /**\n * Private: Apply request interceptors\n */\n private async applyRequestInterceptors(config: RequestConfig): Promise<RequestConfig> {\n let result = config;\n for (const interceptor of this.requestInterceptors) {\n result = await interceptor(result);\n }\n return result;\n }\n\n /**\n * Private: Apply response interceptors\n */\n private async applyResponseInterceptors<T>(response: RevragResponse<T>): Promise<RevragResponse<T>> {\n let result: RevragResponse<T> = response;\n for (const interceptor of this.responseInterceptors) {\n result = await interceptor(result) as RevragResponse<T>;\n }\n return result;\n }\n\n /**\n * Private: Execute request with retry logic\n */\n private async executeWithRetry<T>(url: string, config: RequestConfig): Promise<RevragResponse<T>> {\n const maxRetries = config.retries || 0;\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n // Add exponential backoff for retries\n if (attempt > 0) {\n const delay = Math.min(1000 * Math.pow(2, attempt - 1), 10000);\n await this.delay(delay);\n }\n\n const response = await this.executeRequest<T>(url, config);\n return response;\n \n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n \n // Don't retry for certain error types\n if (this.shouldNotRetry(lastError) || attempt === maxRetries) {\n throw lastError;\n }\n }\n }\n\n throw lastError;\n }\n\n /**\n * Private: Execute single HTTP request\n */\n private async executeRequest<T>(url: string, config: RequestConfig): Promise<RevragResponse<T>> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), config.timeout || this.timeout);\n\n try {\n const response = await fetch(url, {\n ...config,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n throw await this.createHttpError(response);\n }\n\n const data = await response.json();\n \n return {\n success: true,\n data: data as T,\n metadata: {\n timestamp: new Date(),\n requestId: config.metadata?.requestId as string,\n },\n };\n\n } catch (error) {\n clearTimeout(timeoutId);\n \n if (error instanceof Error && error.name === 'AbortError') {\n throw RevragError.timeoutError('Request timed out', config.timeout || this.timeout);\n }\n \n throw error;\n }\n }\n\n /**\n * Private: Create HTTP error from response\n */\n private async createHttpError(response: Response): Promise<RevragError> {\n let errorData: unknown;\n try {\n errorData = await response.json();\n } catch {\n errorData = await response.text();\n }\n\n const statusCode = response.status;\n const statusText = response.statusText;\n\n switch (statusCode) {\n case 401:\n return RevragError.invalidApiKey(`Authentication failed: ${statusText}`);\n case 429: {\n const retryAfter = response.headers.get('Retry-After');\n return RevragError.rateLimitError(\n `Rate limit exceeded: ${statusText}`,\n retryAfter ? parseInt(retryAfter, 10) : undefined\n );\n }\n case 503:\n return RevragError.serviceUnavailable(`Service unavailable: ${statusText}`);\n default:\n return RevragError.networkError(\n `HTTP ${statusCode}: ${statusText}`,\n { statusCode, statusText, data: errorData }\n );\n }\n }\n\n /**\n * Private: Check if error should not be retried\n */\n private shouldNotRetry(error: Error): boolean {\n if (error instanceof RevragError) {\n return error.code === RevragErrorCode.INVALID_API_KEY || \n error.code === RevragErrorCode.VALIDATION_ERROR;\n }\n return false;\n }\n\n /**\n * Private: Delay helper for retry backoff\n */\n private delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n} ","/**\n * @license React\n * react-jsx-runtime.production.min.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';var f=require(\"react\"),k=Symbol.for(\"react.element\"),l=Symbol.for(\"react.fragment\"),m=Object.prototype.hasOwnProperty,n=f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,p={key:!0,ref:!0,__self:!0,__source:!0};\nfunction q(c,a,g){var b,d={},e=null,h=null;void 0!==g&&(e=\"\"+g);void 0!==a.key&&(e=\"\"+a.key);void 0!==a.ref&&(h=a.ref);for(b in a)m.call(a,b)&&!p.hasOwnProperty(b)&&(d[b]=a[b]);if(c&&c.defaultProps)for(b in a=c.defaultProps,a)void 0===d[b]&&(d[b]=a[b]);return{$$typeof:k,type:c,key:e,ref:h,props:d,_owner:n.current}}exports.Fragment=l;exports.jsx=q;exports.jsxs=q;\n","/**\n * @license React\n * react-jsx-runtime.development.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nif (process.env.NODE_ENV !== \"production\") {\n (function() {\n'use strict';\n\nvar React = require('react');\n\n// ATTENTION\n// When adding new symbols to this file,\n// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'\n// The Symbol used to tag the ReactElement-like types.\nvar REACT_ELEMENT_TYPE = Symbol.for('react.element');\nvar REACT_PORTAL_TYPE = Symbol.for('react.portal');\nvar REACT_FRAGMENT_TYPE = Symbol.for('react.fragment');\nvar REACT_STRICT_MODE_TYPE = Symbol.for('react.strict_mode');\nvar REACT_PROFILER_TYPE = Symbol.for('react.profiler');\nvar REACT_PROVIDER_TYPE = Symbol.for('react.provider');\nvar REACT_CONTEXT_TYPE = Symbol.for('react.context');\nvar REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref');\nvar REACT_SUSPENSE_TYPE = Symbol.for('react.suspense');\nvar REACT_SUSPENSE_LIST_TYPE = Symbol.for('react.suspense_list');\nvar REACT_MEMO_TYPE = Symbol.for('react.memo');\nvar REACT_LAZY_TYPE = Symbol.for('react.lazy');\nvar REACT_OFFSCREEN_TYPE = Symbol.for('react.offscreen');\nvar MAYBE_ITERATOR_SYMBOL = Symbol.iterator;\nvar FAUX_ITERATOR_SYMBOL = '@@iterator';\nfunction getIteratorFn(maybeIterable) {\n if (maybeIterable === null || typeof maybeIterable !== 'object') {\n return null;\n }\n\n var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];\n\n if (typeof maybeIterator === 'function') {\n return maybeIterator;\n }\n\n return null;\n}\n\nvar ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n\nfunction error(format) {\n {\n {\n for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n args[_key2 - 1] = arguments[_key2];\n }\n\n printWarning('error', format, args);\n }\n }\n}\n\nfunction printWarning(level, format, args) {\n // When changing this logic, you might want to also\n // update consoleWithStackDev.www.js as well.\n {\n var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;\n var stack = ReactDebugCurrentFrame.getStackAddendum();\n\n if (stack !== '') {\n format += '%s';\n args = args.concat([stack]);\n } // eslint-disable-next-line react-internal/safe-string-coercion\n\n\n var argsWithFormat = args.map(function (item) {\n return String(item);\n }); // Careful: RN currently depends on this prefix\n\n argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it\n // breaks IE9: https://github.com/facebook/react/issues/13610\n // eslint-disable-next-line react-internal/no-production-logging\n\n Function.prototype.apply.call(console[level], console, argsWithFormat);\n }\n}\n\n// -----------------------------------------------------------------------------\n\nvar enableScopeAPI = false; // Experimental Create Event Handle API.\nvar enableCacheElement = false;\nvar enableTransitionTracing = false; // No known bugs, but needs performance testing\n\nvar enableLegacyHidden = false; // Enables unstable_avoidThisFallback feature in Fiber\n// stuff. Intended to enable React core members to more easily debug scheduling\n// issues in DEV builds.\n\nvar enableDebugTracing = false; // Track which Fiber(s) schedule render work.\n\nvar REACT_MODULE_REFERENCE;\n\n{\n REACT_MODULE_REFERENCE = Symbol.for('react.module.reference');\n}\n\nfunction isValidElementType(type) {\n if (typeof type === 'string' || typeof type === 'function') {\n return true;\n } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill).\n\n\n if (type === REACT_FRAGMENT_TYPE || type === REACT_PROFILER_TYPE || enableDebugTracing || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || enableLegacyHidden || type === REACT_OFFSCREEN_TYPE || enableScopeAPI || enableCacheElement || enableTransitionTracing ) {\n return true;\n }\n\n if (typeof type === 'object' && type !== null) {\n if (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || // This needs to include all possible module reference object\n // types supported by any Flight configuration anywhere since\n // we don't know which Flight build this will end up being used\n // with.\n type.$$typeof === REACT_MODULE_REFERENCE || type.getModuleId !== undefined) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction getWrappedName(outerType, innerType, wrapperName) {\n var displayName = outerType.displayName;\n\n if (displayName) {\n return displayName;\n }\n\n var functionName = innerType.displayName || innerType.name || '';\n return functionName !== '' ? wrapperName + \"(\" + functionName + \")\" : wrapperName;\n} // Keep in sync with react-reconciler/getComponentNameFromFiber\n\n\nfunction getContextName(type) {\n return type.displayName || 'Context';\n} // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead.\n\n\nfunction getComponentNameFromType(type) {\n if (type == null) {\n // Host root, text node or just invalid type.\n return null;\n }\n\n {\n if (typeof type.tag === 'number') {\n error('Received an unexpected object in getComponentNameFromType(). ' + 'This is likely a bug in React. Please file an issue.');\n }\n }\n\n if (typeof type === 'function') {\n return type.displayName || type.name || null;\n }\n\n if (typeof type === 'string') {\n return type;\n }\n\n switch (type) {\n case REACT_FRAGMENT_TYPE:\n return 'Fragment';\n\n case REACT_PORTAL_TYPE:\n return 'Portal';\n\n case REACT_PROFILER_TYPE:\n return 'Profiler';\n\n case REACT_STRICT_MODE_TYPE:\n return 'StrictMode';\n\n case REACT_SUSPENSE_TYPE:\n return 'Suspense';\n\n case REACT_SUSPENSE_LIST_TYPE:\n return 'SuspenseList';\n\n }\n\n if (typeof type === 'object') {\n switch (type.$$typeof) {\n case REACT_CONTEXT_TYPE:\n var context = type;\n return getContextName(context) + '.Consumer';\n\n case REACT_PROVIDER_TYPE:\n var provider = type;\n return getContextName(provider._context) + '.Provider';\n\n case REACT_FORWARD_REF_TYPE:\n return getWrappedName(type, type.render, 'ForwardRef');\n\n case REACT_MEMO_TYPE:\n var outerName = type.displayName || null;\n\n if (outerName !== null) {\n return outerName;\n }\n\n return getComponentNameFromType(type.type) || 'Memo';\n\n case REACT_LAZY_TYPE:\n {\n var lazyComponent = type;\n var payload = lazyComponent._payload;\n var init = lazyComponent._init;\n\n try {\n return getComponentNameFromType(init(payload));\n } catch (x) {\n return null;\n }\n }\n\n // eslint-disable-next-line no-fallthrough\n }\n }\n\n return null;\n}\n\nvar assign = Object.assign;\n\n// Helpers to patch console.logs to avoid logging during side-effect free\n// replaying on render function. This currently only patches the object\n// lazily which won't cover if the log function was extracted eagerly.\n// We could also eagerly patch the method.\nvar disabledDepth = 0;\nvar prevLog;\nvar prevInfo;\nvar prevWarn;\nvar prevError;\nvar prevGroup;\nvar prevGroupCollapsed;\nvar prevGroupEnd;\n\nfunction disabledLog() {}\n\ndisabledLog.__reactDisabledLog = true;\nfunction disableLogs() {\n {\n if (disabledDepth === 0) {\n /* eslint-disable react-internal/no-production-logging */\n prevLog = console.log;\n prevInfo = console.info;\n prevWarn = console.warn;\n prevError = console.error;\n prevGroup = console.group;\n prevGroupCollapsed = console.groupCollapsed;\n prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099\n\n var props = {\n configurable: true,\n enumerable: true,\n value: disabledLog,\n writable: true\n }; // $FlowFixMe Flow thinks console is immutable.\n\n Object.defineProperties(console, {\n info: props,\n log: props,\n warn: props,\n error: props,\n group: props,\n groupCollapsed: props,\n groupEnd: props\n });\n /* eslint-enable react-internal/no-production-logging */\n }\n\n disabledDepth++;\n }\n}\nfunction reenableLogs() {\n {\n disabledDepth--;\n\n if (disabledDepth === 0) {\n /* eslint-disable react-internal/no-production-logging */\n var props = {\n configurable: true,\n enumerable: true,\n writable: true\n }; // $FlowFixMe Flow thinks console is immutable.\n\n Object.defineProperties(console, {\n log: assign({}, props, {\n value: prevLog\n }),\n info: assign({}, props, {\n value: prevInfo\n }),\n warn: assign({}, props, {\n value: prevWarn\n }),\n error: assign({}, props, {\n value: prevError\n }),\n group: assign({}, props, {\n value: prevGroup\n }),\n groupCollapsed: assign({}, props, {\n value: prevGroupCollapsed\n }),\n groupEnd: assign({}, props, {\n value: prevGroupEnd\n })\n });\n /* eslint-enable react-internal/no-production-logging */\n }\n\n if (disabledDepth < 0) {\n error('disabledDepth fell below zero. ' + 'This is a bug in React. Please file an issue.');\n }\n }\n}\n\nvar ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher;\nvar prefix;\nfunction describeBuiltInComponentFrame(name, source, ownerFn) {\n {\n if (prefix === undefined) {\n // Extract the VM specific prefix used by each line.\n try {\n throw Error();\n } catch (x) {\n var match = x.stack.trim().match(/\\n( *(at )?)/);\n prefix = match && match[1] || '';\n }\n } // We use the prefix to ensure our stacks line up with native stack frames.\n\n\n return '\\n' + prefix + name;\n }\n}\nvar reentry = false;\nvar componentFrameCache;\n\n{\n var PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map;\n componentFrameCache = new PossiblyWeakMap();\n}\n\nfunction describeNativeComponentFrame(fn, construct) {\n // If something asked for a stack inside a fake render, it should get ignored.\n if ( !fn || reentry) {\n return '';\n }\n\n {\n var frame = componentFrameCache.get(fn);\n\n if (frame !== undefined) {\n return frame;\n }\n }\n\n var control;\n reentry = true;\n var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe It does accept undefined.\n\n Error.prepareStackTrace = undefined;\n var previousDispatcher;\n\n {\n previousDispatcher = ReactCurrentDispatcher.current; // Set the dispatcher in DEV because this might be call in the render function\n // for warnings.\n\n ReactCurrentDispatcher.current = null;\n disableLogs();\n }\n\n try {\n // This should throw.\n if (construct) {\n // Something should be setting the props in the constructor.\n var Fake = function () {\n throw Error();\n }; // $FlowFixMe\n\n\n Object.defineProperty(Fake.prototype, 'props', {\n set: function () {\n // We use a throwing setter instead of frozen or non-writable props\n // because that won't throw in a non-strict mode function.\n throw Error();\n }\n });\n\n if (typeof Reflect === 'object' && Reflect.construct) {\n // We construct a different control for this case to include any extra\n // frames added by the construct call.\n try {\n Reflect.construct(Fake, []);\n } catch (x) {\n control = x;\n }\n\n Reflect.construct(fn, [], Fake);\n } else {\n try {\n Fake.call();\n } catch (x) {\n control = x;\n }\n\n fn.call(Fake.prototype);\n }\n } else {\n try {\n throw Error();\n } catch (x) {\n control = x;\n }\n\n fn();\n }\n } catch (sample) {\n // This is inlined manually because closure doesn't do it for us.\n if (sample && control && typeof sample.stack === 'string') {\n // This extracts the first frame from the sample that isn't also in the control.\n // Skipping one frame that we assume is the frame that calls the two.\n var sampleLines = sample.stack.split('\\n');\n var controlLines = control.stack.split('\\n');\n var s = sampleLines.length - 1;\n var c = controlLines.length - 1;\n\n while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) {\n // We expect at least one stack frame to be shared.\n // Typically this will be the root most one. However, stack frames may be\n // cut off due to maximum stack limits. In this case, one maybe cut off\n // earlier than the other. We assume that the sample is longer or the same\n // and there for cut off earlier. So we should find the root most frame in\n // the sample somewhere in the control.\n c--;\n }\n\n for (; s >= 1 && c >= 0; s--, c--) {\n // Next we find the first one that isn't the same which should be the\n // frame that called our sample function and the control.\n if (sampleLines[s] !== cont