@alter-ai/connect 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alter-connect.umd.js","sources":["../src/core/config.ts","../src/core/events.ts","../src/state/manager.ts","../src/api/client.ts","../src/ui/modal.ts","../src/ui/provider-list.ts","../src/oauth/handler.ts","../src/core/alter-connect.ts"],"sourcesContent":["/**\n * Configuration validation and management\n */\n\nimport type { AlterConnectConfig } from '../types';\n\n/**\n * Explicit type for required config with all nested properties\n */\ninterface FullConfig {\n customization: {\n colors: {\n primary: string;\n text: string;\n background: string;\n };\n fontFamily: string;\n logoUrl?: string;\n };\n locale: string;\n debug: boolean;\n}\n\n/**\n * Default configuration values\n */\nconst DEFAULT_CONFIG: FullConfig = {\n customization: {\n colors: {\n primary: '#6366f1',\n text: '#1f2937',\n background: '#ffffff',\n },\n fontFamily: '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif',\n },\n locale: 'en',\n debug: false,\n};\n\n/**\n * Validate configuration\n */\nexport function validateConfig(config: AlterConnectConfig): void {\n if (config.customization?.colors?.primary) {\n if (!isValidColor(config.customization.colors.primary)) {\n throw new Error(`Invalid primary color: ${config.customization.colors.primary}`);\n }\n }\n\n if (config.customization?.colors?.text) {\n if (!isValidColor(config.customization.colors.text)) {\n throw new Error(`Invalid text color: ${config.customization.colors.text}`);\n }\n }\n\n if (config.customization?.colors?.background) {\n if (!isValidColor(config.customization.colors.background)) {\n throw new Error(`Invalid background color: ${config.customization.colors.background}`);\n }\n }\n}\n\n/**\n * Merge user config with defaults\n */\nexport function mergeConfig(config: AlterConnectConfig): FullConfig {\n const defaultColors = DEFAULT_CONFIG.customization.colors;\n const defaultFont = DEFAULT_CONFIG.customization.fontFamily;\n\n return {\n customization: {\n colors: {\n primary: config.customization?.colors?.primary || defaultColors.primary,\n text: config.customization?.colors?.text || defaultColors.text,\n background: config.customization?.colors?.background || defaultColors.background,\n },\n fontFamily: config.customization?.fontFamily || defaultFont,\n },\n locale: config.locale || DEFAULT_CONFIG.locale,\n debug: config.debug ?? DEFAULT_CONFIG.debug,\n };\n}\n\n/**\n * Debug logging helper\n */\nexport function debugLog(config: FullConfig, ...args: any[]): void {\n if (config.debug) {\n console.log('[Alter Connect]', ...args);\n }\n}\n\n/**\n * Export FullConfig type for use in other modules\n */\nexport type { FullConfig };\n\n/**\n * Validate color string (hex, rgb, rgba, named colors)\n */\nfunction isValidColor(color: string): boolean {\n // Hex colors\n if (/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(color)) {\n return true;\n }\n\n // RGB/RGBA\n if (/^rgba?\\(\\s*\\d+\\s*,\\s*\\d+\\s*,\\s*\\d+\\s*(,\\s*[\\d.]+\\s*)?\\)$/.test(color)) {\n return true;\n }\n\n // HSL/HSLA\n if (/^hsla?\\(\\s*\\d+\\s*,\\s*[\\d.]+%\\s*,\\s*[\\d.]+%\\s*(,\\s*[\\d.]+\\s*)?\\)$/.test(color)) {\n return true;\n }\n\n // Named colors (basic validation - just check if it's a word)\n if (/^[a-z]+$/.test(color.toLowerCase())) {\n return true;\n }\n\n return false;\n}\n","/**\n * Simple event emitter for SDK events\n */\n\ntype EventHandler = (...args: any[]) => void;\n\n/**\n * Event emitter for SDK internal events\n */\nexport class EventEmitter {\n private events: Map<string, Set<EventHandler>>;\n\n constructor() {\n this.events = new Map();\n }\n\n /**\n * Register an event listener\n * @returns Unsubscribe function\n */\n on(event: string, handler: EventHandler): () => void {\n if (!this.events.has(event)) {\n this.events.set(event, new Set());\n }\n\n this.events.get(event)!.add(handler);\n\n // Return unsubscribe function\n return () => this.off(event, handler);\n }\n\n /**\n * Remove an event listener\n */\n off(event: string, handler: EventHandler): void {\n const handlers = this.events.get(event);\n if (handlers) {\n handlers.delete(handler);\n }\n }\n\n /**\n * Emit an event\n */\n emit(event: string, ...args: any[]): void {\n const handlers = this.events.get(event);\n if (handlers) {\n handlers.forEach(handler => {\n try {\n handler(...args);\n } catch (error) {\n console.error(`[Alter Connect] Error in event handler for '${event}':`, error);\n }\n });\n }\n }\n\n /**\n * Remove all listeners for an event, or all listeners if no event specified\n */\n removeAllListeners(event?: string): void {\n if (event) {\n this.events.delete(event);\n } else {\n this.events.clear();\n }\n }\n}\n","/**\n * State management for SDK\n */\n\nimport type { Provider, AlterError } from '../types';\n\n/**\n * SDK internal state\n */\nexport interface SDKState {\n isOpen: boolean;\n isLoading: boolean;\n error: AlterError | null;\n sessionToken: string | null;\n providers: Provider[];\n selectedProvider: Provider | null;\n searchQuery: string;\n categoryFilter: string | null;\n}\n\ntype StateListener = (state: SDKState) => void;\n\n/**\n * Simple state manager\n */\nexport class StateManager {\n private state: SDKState;\n private listeners: Set<StateListener>;\n\n constructor() {\n this.state = {\n isOpen: false,\n isLoading: false,\n error: null,\n sessionToken: null,\n providers: [],\n selectedProvider: null,\n searchQuery: '',\n categoryFilter: null,\n };\n this.listeners = new Set();\n }\n\n /**\n * Get current state\n */\n getState(): Readonly<SDKState> {\n return { ...this.state };\n }\n\n /**\n * Get a specific state value\n */\n get<K extends keyof SDKState>(key: K): SDKState[K] {\n return this.state[key];\n }\n\n /**\n * Update state\n */\n setState(updates: Partial<SDKState>): void {\n this.state = { ...this.state, ...updates };\n this.notifyListeners();\n }\n\n /**\n * Subscribe to state changes\n */\n subscribe(listener: StateListener): () => void {\n this.listeners.add(listener);\n\n // Return unsubscribe function\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n /**\n * Clear all listeners\n */\n clearListeners(): void {\n this.listeners.clear();\n }\n\n /**\n * Notify all listeners of state change\n */\n private notifyListeners(): void {\n const currentState = this.getState();\n this.listeners.forEach(listener => {\n try {\n listener(currentState);\n } catch (error) {\n console.error('[Alter Connect] Error in state listener:', error);\n }\n });\n }\n}\n","/**\n * API client for Alter Vault backend\n */\n\nimport type { Provider, AlterError } from '../types';\n\n/**\n * API client for communicating with Alter Vault\n * All requests use session tokens (no API key in frontend)\n */\nexport class AlterAPIClient {\n private debug: boolean;\n private readonly TIMEOUT = 30000; // 30 seconds\n private readonly DEFAULT_BASE_URL = 'https://api.alterai.dev';\n\n constructor(debug: boolean = false) {\n this.debug = debug;\n }\n\n /**\n * Fetch available providers using session token\n */\n async fetchProviders(sessionToken: string, baseURL?: string): Promise<Provider[]> {\n this.log('Fetching providers with session token');\n\n const response = await this.fetch<{ providers: Provider[] }>('/oauth/providers', {\n method: 'GET',\n sessionToken,\n baseURL: baseURL || this.DEFAULT_BASE_URL,\n });\n\n this.log(`Fetched ${response.providers.length} providers`);\n return response.providers;\n }\n\n /**\n * Fetch branding configuration using session token\n */\n async fetchBranding(sessionToken: string, baseURL?: string): Promise<any> {\n this.log('Fetching branding with session token');\n\n const response = await this.fetch<any>('/oauth/branding', {\n method: 'GET',\n sessionToken,\n baseURL: baseURL || this.DEFAULT_BASE_URL,\n });\n\n this.log('Fetched branding:', response);\n return response;\n }\n\n /**\n * Build authorization URL for a provider\n */\n buildAuthorizationURL(providerId: string, sessionToken: string, baseURL?: string): string {\n const base = baseURL || this.DEFAULT_BASE_URL;\n const url = `${base}/oauth/connect/initiate?provider=${providerId}&session=${sessionToken}`;\n this.log('Authorization URL:', url);\n return url;\n }\n\n /**\n * Generic fetch wrapper with error handling\n */\n private async fetch<T>(\n endpoint: string,\n options: {\n method: string;\n sessionToken?: string;\n body?: string;\n baseURL: string;\n }\n ): Promise<T> {\n const url = `${options.baseURL}${endpoint}`;\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n // Add session token if provided\n if (options.sessionToken) {\n headers['X-Session-Token'] = options.sessionToken;\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.TIMEOUT);\n\n try {\n const response = await fetch(url, {\n method: options.method,\n headers,\n body: options.body,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({\n error: 'unknown_error',\n message: `HTTP ${response.status}: ${response.statusText}`,\n }));\n\n throw this.createError(\n errorData.error || 'api_error',\n errorData.message || errorData.error_description || `Request failed with status ${response.status}`,\n errorData\n );\n }\n\n return await response.json();\n } catch (error: any) {\n clearTimeout(timeoutId);\n\n // Handle network errors\n if (error.name === 'AbortError') {\n throw this.createError(\n 'timeout',\n `Request timed out after ${this.TIMEOUT}ms`,\n { timeout: this.TIMEOUT }\n );\n }\n\n // Handle fetch errors (network issues)\n if (error instanceof TypeError) {\n throw this.createError(\n 'network_error',\n 'Network request failed. Please check your internet connection.',\n { originalError: error.message }\n );\n }\n\n // Re-throw AlterError instances\n if (this.isAlterError(error)) {\n throw error;\n }\n\n // Wrap unknown errors\n throw this.createError('unknown_error', error.message || 'An unexpected error occurred', {\n originalError: error,\n });\n }\n }\n\n /**\n * Create an AlterError object\n */\n private createError(code: string, message: string, details?: Record<string, any>): AlterError {\n return {\n code,\n message,\n details,\n };\n }\n\n /**\n * Check if an error is an AlterError\n */\n private isAlterError(error: any): error is AlterError {\n return error && typeof error === 'object' && 'code' in error && 'message' in error;\n }\n\n /**\n * Log debug message\n */\n private log(...args: any[]): void {\n if (this.debug) {\n console.log('[Alter API Client]', ...args);\n }\n }\n}\n","/**\n * Modal UI component\n */\n\nimport type { FullConfig } from '../core/config';\n\ninterface ModalOptions {\n onClose: () => void;\n}\n\n/**\n * Modal overlay component\n */\nexport class Modal {\n private overlay: HTMLElement | null = null;\n private container: HTMLElement | null = null;\n private contentEl: HTMLElement | null = null;\n private closeButton: HTMLElement | null = null;\n private config: FullConfig;\n private onClose: (() => void) | null = null;\n\n constructor(config: FullConfig) {\n this.config = config;\n }\n\n /**\n * Open modal\n */\n open(options: ModalOptions): void {\n this.onClose = options.onClose;\n\n // Create overlay\n this.overlay = document.createElement('div');\n this.overlay.className = 'alter-connect-overlay';\n this.overlay.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 999999;\n animation: alter-connect-fade-in 0.2s ease-out;\n `;\n\n // Create modal container (matching connect.html template - white background)\n this.container = document.createElement('div');\n this.container.className = 'alter-connect-modal';\n this.container.style.cssText = `\n background: #ffffff;\n border-radius: 12px;\n box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);\n width: 90%;\n max-width: 480px;\n max-height: 90vh;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n font-family: ${this.config.customization.fontFamily};\n animation: alter-connect-slide-up 0.3s ease-out;\n color: #1a1a1a;\n `;\n\n // Create close button (matching connect.html - dark on white)\n this.closeButton = document.createElement('button');\n this.closeButton.className = 'alter-connect-close';\n this.closeButton.innerHTML = '&times;';\n this.closeButton.setAttribute('aria-label', 'Close');\n this.closeButton.style.cssText = `\n position: absolute;\n top: 16px;\n right: 16px;\n background: transparent;\n border: none;\n font-size: 28px;\n line-height: 1;\n color: #6b7280;\n cursor: pointer;\n padding: 0;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n transition: background-color 0.2s, color 0.2s;\n `;\n this.closeButton.addEventListener('click', () => this.handleClose());\n this.closeButton.addEventListener('mouseenter', () => {\n this.closeButton!.style.backgroundColor = '#f3f4f6';\n this.closeButton!.style.color = '#111827';\n });\n this.closeButton.addEventListener('mouseleave', () => {\n this.closeButton!.style.backgroundColor = 'transparent';\n this.closeButton!.style.color = '#6b7280';\n });\n\n // Create content container\n this.contentEl = document.createElement('div');\n this.contentEl.className = 'alter-connect-content';\n this.contentEl.style.cssText = `\n padding: 40px 32px 32px 32px;\n overflow-y: auto;\n flex: 1;\n position: relative;\n `;\n\n // Assemble modal\n this.container.appendChild(this.closeButton);\n this.container.appendChild(this.contentEl);\n this.overlay.appendChild(this.container);\n\n // Add to DOM\n document.body.appendChild(this.overlay);\n\n // Close on overlay click (but not modal click)\n this.overlay.addEventListener('click', (e) => {\n if (e.target === this.overlay) {\n this.handleClose();\n }\n });\n\n // Close on Escape key\n document.addEventListener('keydown', this.handleEscape);\n\n // Prevent body scroll\n document.body.style.overflow = 'hidden';\n }\n\n /**\n * Set modal content\n */\n setContent(content: HTMLElement): void {\n if (this.contentEl) {\n this.contentEl.innerHTML = '';\n this.contentEl.appendChild(content);\n }\n }\n\n /**\n * Close modal\n */\n close(): void {\n // Remove from DOM\n if (this.overlay && this.overlay.parentNode) {\n this.overlay.parentNode.removeChild(this.overlay);\n }\n\n // Clean up references\n this.overlay = null;\n this.container = null;\n this.contentEl = null;\n this.closeButton = null;\n this.onClose = null;\n\n // Remove escape listener\n document.removeEventListener('keydown', this.handleEscape);\n\n // Restore body scroll\n document.body.style.overflow = '';\n }\n\n /**\n * Destroy modal (same as close for now)\n */\n destroy(): void {\n this.close();\n }\n\n /**\n * Handle close event\n */\n private handleClose = (): void => {\n if (this.onClose) {\n this.onClose();\n }\n };\n\n /**\n * Handle Escape key\n */\n private handleEscape = (e: KeyboardEvent): void => {\n if (e.key === 'Escape') {\n this.handleClose();\n }\n };\n}\n\n/**\n * Inject global styles for animations\n */\nexport function injectGlobalStyles(): void {\n // Check if styles already injected\n if (document.getElementById('alter-connect-styles')) {\n return;\n }\n\n const style = document.createElement('style');\n style.id = 'alter-connect-styles';\n style.textContent = `\n @keyframes alter-connect-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n\n @keyframes alter-connect-slide-up {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .alter-connect-modal * {\n box-sizing: border-box;\n }\n `;\n\n document.head.appendChild(style);\n}\n","/**\n * Provider list UI component\n */\n\nimport type { Provider } from '../types';\nimport type { FullConfig } from '../core/config';\n\ntype ProviderClickHandler = (provider: Provider) => void;\n\n/**\n * Provider list component\n */\nexport class ProviderList {\n private container: HTMLElement | null = null;\n private config: FullConfig;\n private onProviderClick: ProviderClickHandler | null = null;\n\n constructor(config: FullConfig) {\n this.config = config;\n }\n\n /**\n * Render provider list\n */\n render(providers: Provider[], onProviderClick: ProviderClickHandler): HTMLElement {\n this.onProviderClick = onProviderClick;\n\n // Create container (matching connect.html template - grid layout)\n this.container = document.createElement('div');\n this.container.className = 'alter-connect-provider-list';\n this.container.style.cssText = `\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n gap: 12px;\n margin-bottom: 20px;\n `;\n\n // Render providers\n this.renderProviders(providers);\n\n return this.container;\n }\n\n /**\n * Update provider list\n */\n update(providers: Provider[]): void {\n if (this.container) {\n this.container.innerHTML = '';\n this.renderProviders(providers);\n }\n }\n\n /**\n * Destroy component\n */\n destroy(): void {\n this.container = null;\n this.onProviderClick = null;\n }\n\n /**\n * Render provider buttons\n */\n private renderProviders(providers: Provider[]): void {\n if (!this.container) return;\n\n if (providers.length === 0) {\n // Show empty state\n const emptyState = document.createElement('div');\n emptyState.style.cssText = `\n text-align: center;\n padding: 40px 20px;\n color: white;\n font-size: 14px;\n `;\n emptyState.textContent = 'No providers found';\n this.container.appendChild(emptyState);\n return;\n }\n\n providers.forEach(provider => {\n const button = this.createProviderButton(provider);\n this.container!.appendChild(button);\n });\n }\n\n /**\n * Create provider button\n */\n private createProviderButton(provider: Provider): HTMLElement {\n // Create card (matching connect.html template)\n const button = document.createElement('button');\n button.className = 'alter-connect-provider-button';\n button.setAttribute('data-provider-id', provider.id);\n button.style.cssText = `\n display: flex;\n align-items: center;\n padding: 16px;\n background: white;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.15s;\n text-decoration: none;\n color: inherit;\n gap: 12px;\n font-family: ${this.config.customization.fontFamily};\n width: 100%;\n `;\n\n // Arrow (need to define early for hover effect)\n const arrow = document.createElement('span');\n arrow.textContent = '→';\n arrow.className = 'connect-arrow';\n arrow.style.cssText = `\n color: #9ca3af;\n font-size: 18px;\n transition: all 0.15s;\n flex-shrink: 0;\n `;\n\n // Hover effect\n button.addEventListener('mouseenter', () => {\n button.style.borderColor = '#d1d5db';\n button.style.boxShadow = '0 2px 8px rgba(0, 0, 0, 0.08)';\n button.style.transform = 'translateY(-1px)';\n arrow.style.color = '#000000';\n arrow.style.transform = 'translateX(2px)';\n });\n\n button.addEventListener('mouseleave', () => {\n button.style.borderColor = '#e5e7eb';\n button.style.boxShadow = 'none';\n button.style.transform = 'translateY(0)';\n arrow.style.color = '#9ca3af';\n arrow.style.transform = 'translateX(0)';\n });\n\n // Provider icon (matching connect.html template)\n const iconContainer = document.createElement('div');\n iconContainer.style.cssText = `\n width: 40px;\n height: 40px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #f9fafb;\n border: 1px solid #e5e7eb;\n flex-shrink: 0;\n `;\n\n // Use logo_url from backend if available\n if (provider.logo_url) {\n const logoImg = document.createElement('img');\n logoImg.src = provider.logo_url;\n logoImg.alt = provider.name;\n logoImg.style.cssText = `\n width: 28px;\n height: 28px;\n object-fit: contain;\n `;\n\n // Fallback to first letter if image fails to load\n logoImg.addEventListener('error', () => {\n iconContainer.textContent = provider.name.charAt(0).toUpperCase();\n });\n\n iconContainer.appendChild(logoImg);\n } else {\n // Fallback to first letter if no logo_url\n iconContainer.textContent = provider.name.charAt(0).toUpperCase();\n }\n\n // Provider info container\n const infoContainer = document.createElement('div');\n infoContainer.style.cssText = `\n flex: 1;\n min-width: 0;\n text-align: left;\n `;\n\n // Provider name\n const name = document.createElement('div');\n name.textContent = provider.name;\n name.style.cssText = `\n font-size: 14px;\n font-weight: 600;\n color: #1a1a1a;\n margin-bottom: 2px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n `;\n\n // Provider category\n const category = document.createElement('div');\n category.textContent = provider.category ? provider.category.charAt(0).toUpperCase() + provider.category.slice(1) : 'Other';\n category.style.cssText = `\n font-size: 12px;\n color: #6b7280;\n font-weight: 400;\n `;\n\n infoContainer.appendChild(name);\n infoContainer.appendChild(category);\n\n // Assemble button\n button.appendChild(iconContainer);\n button.appendChild(infoContainer);\n button.appendChild(arrow);\n\n // Click handler\n button.addEventListener('click', () => {\n if (this.onProviderClick) {\n this.onProviderClick(provider);\n }\n });\n\n return button;\n }\n}\n","/**\n * OAuth popup handler\n */\n\nimport type { Connection, AlterError } from '../types';\n\ninterface OAuthHandlerOptions {\n onSuccess: (connection: Connection) => void;\n onError: (error: AlterError) => void;\n onCancel: () => void;\n popupWidth?: number;\n popupHeight?: number;\n debug?: boolean;\n}\n\n/**\n * Handles OAuth flow in popup window\n */\nexport class OAuthHandler {\n private popup: Window | null = null;\n private pollInterval: number | null = null;\n private messageListener: ((event: MessageEvent) => void) | null = null;\n private options: Required<OAuthHandlerOptions>;\n\n constructor(options: OAuthHandlerOptions) {\n this.options = {\n onSuccess: options.onSuccess,\n onError: options.onError,\n onCancel: options.onCancel,\n popupWidth: options.popupWidth || 450,\n popupHeight: options.popupHeight || 600,\n debug: options.debug || false,\n };\n }\n\n /**\n * Open OAuth popup\n */\n openPopup(url: string): void {\n // Calculate popup position (centered)\n const left = window.screenX + (window.outerWidth - this.options.popupWidth) / 2;\n const top = window.screenY + (window.outerHeight - this.options.popupHeight) / 2;\n\n const features = [\n `width=${this.options.popupWidth}`,\n `height=${this.options.popupHeight}`,\n `left=${left}`,\n `top=${top}`,\n 'resizable=yes',\n 'scrollbars=yes',\n 'status=yes',\n ].join(',');\n\n this.log('Opening OAuth popup:', url);\n\n // Open popup\n this.popup = window.open(url, 'alter_oauth_popup', features);\n\n if (!this.popup) {\n this.options.onError({\n code: 'popup_blocked',\n message: 'Popup was blocked by browser. Please allow popups for this site.',\n });\n return;\n }\n\n // Start monitoring popup\n this.startPolling();\n this.setupMessageListener();\n }\n\n /**\n * Close popup and clean up\n */\n close(): void {\n this.log('Closing OAuth handler');\n\n // Close popup\n if (this.popup && !this.popup.closed) {\n this.popup.close();\n }\n this.popup = null;\n\n // Stop polling\n if (this.pollInterval !== null) {\n clearInterval(this.pollInterval);\n this.pollInterval = null;\n }\n\n // Remove message listener\n if (this.messageListener) {\n window.removeEventListener('message', this.messageListener);\n this.messageListener = null;\n }\n }\n\n /**\n * Poll to detect when popup is closed\n */\n private startPolling(): void {\n this.pollInterval = window.setInterval(() => {\n if (!this.popup || this.popup.closed) {\n this.log('Popup closed by user');\n this.close();\n this.options.onCancel();\n }\n }, 500);\n }\n\n /**\n * Listen for postMessage from OAuth callback page\n */\n private setupMessageListener(): void {\n this.messageListener = (event: MessageEvent) => {\n // Validate origin (in production, should check against allowed origins)\n // For now, we accept messages from any origin for flexibility\n this.log('Received message:', event.data);\n\n const data = event.data;\n\n // Check message type\n if (data && typeof data === 'object') {\n if (data.type === 'alter_connect_success') {\n this.log('OAuth success');\n\n const connection: Connection = {\n connection_id: data.connection_id,\n provider: data.provider,\n provider_name: data.provider_name || data.provider, // Fallback to ID if name not provided\n account_identifier: data.account_identifier,\n timestamp: data.timestamp,\n operation: data.operation || 'creation', // Default to creation for backward compatibility\n scopes: data.scopes || [], // Default to empty array\n status: data.status || 'active', // Default to active\n metadata: data.metadata, // Optional\n };\n\n this.close();\n this.options.onSuccess(connection);\n } else if (data.type === 'alter_connect_error') {\n this.log('OAuth error');\n\n const error: AlterError = {\n code: data.error || 'oauth_error',\n message: data.error_description || 'OAuth authorization failed',\n details: data,\n };\n\n this.close();\n this.options.onError(error);\n }\n }\n };\n\n window.addEventListener('message', this.messageListener);\n }\n\n /**\n * Log debug message\n */\n private log(...args: any[]): void {\n if (this.options.debug) {\n console.log('[OAuth Handler]', ...args);\n }\n }\n}\n","/**\n * Main AlterConnect SDK class\n */\n\nimport type { AlterConnectConfig, OpenOptions, Connection, AlterError, Provider } from '../types';\nimport { validateConfig, mergeConfig, debugLog, type FullConfig } from './config';\nimport { EventEmitter } from './events';\nimport { StateManager } from '../state/manager';\nimport { AlterAPIClient } from '../api/client';\nimport { Modal, injectGlobalStyles } from '../ui/modal';\nimport { ProviderList } from '../ui/provider-list';\nimport { SearchBar } from '../ui/search-bar';\nimport { OAuthHandler } from '../oauth/handler';\n\n/**\n * SDK version\n */\nconst VERSION = '0.1.0';\n\n/**\n * Main SDK class\n */\nexport class AlterConnect {\n private config: FullConfig;\n private eventEmitter: EventEmitter;\n private stateManager: StateManager;\n private apiClient: AlterAPIClient;\n private _modal: Modal;\n private _isInitialized: boolean;\n private _searchBar: SearchBar | null = null;\n private _providerList: ProviderList | null = null;\n private _oauthHandler: OAuthHandler | null = null;\n private _baseURL: string = 'https://api.alterai.dev'; // Default, overridden in open()\n\n /**\n * Private constructor (use AlterConnect.create() instead)\n */\n private constructor(config: AlterConnectConfig = {}) {\n // Validate and merge config\n validateConfig(config);\n this.config = mergeConfig(config);\n\n // Initialize components\n this.eventEmitter = new EventEmitter();\n this.stateManager = new StateManager();\n this.apiClient = new AlterAPIClient(this.config.debug);\n this._modal = new Modal(this.config);\n this._isInitialized = true;\n\n // Inject global styles once\n injectGlobalStyles();\n\n debugLog(this.config, 'Alter Connect SDK initialized', { version: VERSION });\n }\n\n /**\n * Create a new AlterConnect instance\n *\n * @param config Optional configuration for customization (colors, locale, etc.)\n * @returns AlterConnect instance\n *\n * @example\n * // Minimal - uses all defaults\n * const alterConnect = AlterConnect.create();\n *\n * // With customization\n * const alterConnect = AlterConnect.create({\n * customization: {\n * colors: { primary: '#6366f1' }\n * },\n * locale: 'en',\n * debug: true\n * });\n */\n static create(config?: AlterConnectConfig): AlterConnect {\n return new AlterConnect(config);\n }\n\n /**\n * Open the Connect UI with a session token from your backend\n *\n * @param options Configuration including the session token from your backend\n *\n * @example\n * // 1. Get session token from YOUR backend\n * const { session_token } = await fetch('/api/alter/create-session').then(r => r.json());\n *\n * // 2. Open Connect UI\n * await alterConnect.open({\n * token: session_token,\n * onSuccess: (connection) => {\n * console.log('Connected!', connection);\n * // Send connection to your backend\n * },\n * onError: (error) => {\n * console.error('Failed:', error);\n * }\n * });\n */\n async open(options: OpenOptions): Promise<void> {\n // Check if SDK has been destroyed\n if (!this._isInitialized) {\n throw this.createError('sdk_destroyed', 'Cannot call open() - SDK instance has been destroyed');\n }\n\n debugLog(this.config, 'Opening Connect UI');\n\n // Validate required options\n if (!options.token || typeof options.token !== 'string') {\n throw this.createError('invalid_options', 'Session token is required. Create one from your backend using POST /oauth/connect/session');\n }\n\n if (!options.onSuccess || typeof options.onSuccess !== 'function') {\n throw this.createError('invalid_options', 'onSuccess callback is required');\n }\n\n // Check if already open\n if (this.isOpen()) {\n debugLog(this.config, 'Connect UI is already open');\n return;\n }\n\n try {\n // Store baseURL (from backend session response, or default to production)\n this._baseURL = options.baseURL || 'https://api.alterai.dev';\n\n // Update state\n this.stateManager.setState({ isOpen: true, isLoading: true, error: null });\n this.stateManager.setState({ sessionToken: options.token });\n\n // Fetch providers and branding in parallel\n const [providers, branding] = await Promise.all([\n this.apiClient.fetchProviders(options.token, this._baseURL),\n this.apiClient.fetchBranding(options.token, this._baseURL).catch(() => null), // Branding is optional\n ]);\n\n // Apply branding from API (backend returns complete branding with defaults)\n if (branding) {\n debugLog(this.config, 'Applying branding from API');\n\n // Apply colors (backend always returns colors, either custom or defaults)\n if (branding.colors) {\n this.config.customization.colors = {\n primary: branding.colors.primary,\n text: branding.colors.text,\n background: branding.colors.background,\n };\n }\n\n // Apply font family (backend always returns font, either custom or default)\n if (branding.font_family) {\n this.config.customization.fontFamily = branding.font_family;\n }\n\n // Apply logo URL (null = use default Alter logo)\n this.config.customization.logoUrl = branding.logo_url || undefined;\n }\n\n this.stateManager.setState({\n providers,\n isLoading: false,\n });\n\n // Register event handlers\n this.registerEventHandlers(options);\n\n // HYBRID APPROACH: If only 1 provider, skip selection UI and go straight to OAuth\n if (providers.length === 1) {\n debugLog(this.config, 'Single provider detected - skipping selection UI');\n\n // Open OAuth popup immediately\n this.handleProviderClick(providers[0]);\n\n // Emit analytics event\n if (options.onEvent) {\n options.onEvent('single_provider_flow', {\n timestamp: new Date().toISOString(),\n provider: providers[0].id,\n });\n }\n } else {\n debugLog(this.config, 'Multiple providers detected - showing selection UI');\n\n // Build UI content\n const content = this.buildUIContent(providers);\n\n // Set modal content and open\n this._modal.open({\n onClose: () => {\n this.eventEmitter.emit('exit');\n },\n });\n this._modal.setContent(content);\n\n // Emit analytics event\n if (options.onEvent) {\n options.onEvent('modal_opened', {\n timestamp: new Date().toISOString(),\n providerCount: providers.length,\n });\n }\n }\n\n debugLog(this.config, 'Connect UI opened successfully');\n } catch (error: any) {\n debugLog(this.config, 'Error opening Connect UI:', error);\n\n this.stateManager.setState({\n isLoading: false,\n isOpen: false,\n error: this.normalizeError(error),\n });\n\n if (options.onError) {\n options.onError(this.normalizeError(error));\n }\n\n throw error;\n }\n }\n\n /**\n * Close the Connect UI\n */\n close(): void {\n // Check if SDK has been destroyed\n if (!this._isInitialized) {\n throw this.createError('sdk_destroyed', 'Cannot call close() - SDK instance has been destroyed');\n }\n\n debugLog(this.config, 'Closing Connect UI');\n\n // Clean up OAuth handler if active\n if (this._oauthHandler) {\n this._oauthHandler.close();\n this._oauthHandler = null;\n }\n\n // Clean up UI components\n if (this._searchBar) {\n this._searchBar.destroy();\n this._searchBar = null;\n }\n\n if (this._providerList) {\n this._providerList.destroy();\n this._providerList = null;\n }\n\n // Close modal\n this._modal.close();\n\n // Update state\n this.stateManager.setState({\n isOpen: false,\n selectedProvider: null,\n searchQuery: '',\n categoryFilter: null,\n });\n\n this.eventEmitter.emit('close');\n }\n\n /**\n * Destroy the SDK instance and clean up resources\n */\n destroy(): void {\n if (!this._isInitialized) {\n // Already destroyed, silently return\n return;\n }\n\n debugLog(this.config, 'Destroying SDK instance');\n\n // Clean up OAuth handler if active\n if (this._oauthHandler) {\n this._oauthHandler.close();\n this._oauthHandler = null;\n }\n\n // Clean up UI components\n if (this._searchBar) {\n this._searchBar.destroy();\n this._searchBar = null;\n }\n\n if (this._providerList) {\n this._providerList.destroy();\n this._providerList = null;\n }\n\n // Destroy modal\n this._modal.destroy();\n\n // Update state\n if (this.stateManager.get('isOpen')) {\n this.stateManager.setState({\n isOpen: false,\n selectedProvider: null,\n searchQuery: '',\n categoryFilter: null,\n });\n }\n\n // Clean up resources\n this.eventEmitter.removeAllListeners();\n this.stateManager.clearListeners();\n this._isInitialized = false;\n }\n\n /**\n * Update configuration\n */\n updateConfig(config: Partial<AlterConnectConfig>): void {\n // Check if SDK has been destroyed\n if (!this._isInitialized) {\n throw this.createError('sdk_destroyed', 'Cannot call updateConfig() - SDK instance has been destroyed');\n }\n\n debugLog(this.config, 'Updating config', config);\n\n const newConfig = { ...this.config, ...config };\n validateConfig(newConfig);\n this.config = mergeConfig(newConfig);\n\n // Recreate API client with new config (debug flag only)\n this.apiClient = new AlterAPIClient(this.config.debug);\n }\n\n /**\n * Get current configuration\n */\n getConfig(): Required<AlterConnectConfig> {\n return { ...this.config };\n }\n\n /**\n * Register an event listener\n */\n on(event: string, handler: (...args: any[]) => void): () => void {\n // Check if SDK has been destroyed\n if (!this._isInitialized) {\n throw this.createError('sdk_destroyed', 'Cannot call on() - SDK instance has been destroyed');\n }\n\n return this.eventEmitter.on(event, handler);\n }\n\n /**\n * Remove an event listener\n */\n off(event: string, handler: (...args: any[]) => void): void {\n // Check if SDK has been destroyed\n if (!this._isInitialized) {\n throw this.createError('sdk_destroyed', 'Cannot call off() - SDK instance has been destroyed');\n }\n\n this.eventEmitter.off(event, handler);\n }\n\n /**\n * Check if Connect UI is open\n */\n isOpen(): boolean {\n // Check if SDK has been destroyed\n if (!this._isInitialized) {\n throw this.createError('sdk_destroyed', 'Cannot call isOpen() - SDK instance has been destroyed');\n }\n\n return this.stateManager.get('isOpen');\n }\n\n /**\n * Get SDK version\n */\n getVersion(): string {\n return VERSION;\n }\n\n /**\n * Build UI content for the modal (multi-provider case)\n */\n private buildUIContent(providers: Provider[]): HTMLElement {\n const container = document.createElement('div');\n container.className = 'alter-connect-ui-container';\n\n // Header (matching connect.html template - black header bar)\n const headerBar = document.createElement('div');\n headerBar.style.cssText = `\n background: #000000;\n border-bottom: 1px solid #1a1a1a;\n padding: 20px 24px;\n margin: -32px -32px 32px -32px;\n display: flex;\n align-items: center;\n justify-content: center;\n `;\n\n // Logo image (custom or default Alter logo)\n const logo = document.createElement('img');\n\n if (this.config.customization.logoUrl) {\n logo.src = this.config.customization.logoUrl;\n logo.alt = 'App Logo';\n } else {\n logo.src = `${this._baseURL}/static/Alter_Primary_Logo_name.png`;\n logo.alt = 'Alter';\n }\n\n logo.style.cssText = `\n height: 28px;\n width: auto;\n max-width: 200px;\n object-fit: contain;\n `;\n\n // Fallback to text if image fails to load\n logo.addEventListener('error', () => {\n const textLogo = document.createElement('div');\n textLogo.textContent = 'alter';\n textLogo.style.cssText = `\n font-size: 18px;\n font-weight: 600;\n color: #ffffff;\n letter-spacing: -0.02em;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n `;\n logo.replaceWith(textLogo);\n });\n\n headerBar.appendChild(logo);\n\n // Page header\n const header = document.createElement('div');\n header.style.cssText = `\n margin-bottom: 32px;\n text-align: center;\n `;\n\n const title = document.createElement('h1');\n title.textContent = 'Connect an Integration';\n title.style.cssText = `\n font-size: 24px;\n font-weight: 600;\n color: #1a1a1a;\n margin-bottom: 8px;\n letter-spacing: -0.02em;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n `;\n\n const subtitle = document.createElement('p');\n subtitle.textContent = 'Choose a service to connect to your account';\n subtitle.style.cssText = `\n margin: 0;\n font-size: 15px;\n color: #6b7280;\n font-weight: 400;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n `;\n\n header.appendChild(title);\n header.appendChild(subtitle);\n\n // Provider list (no search bar - matching connect.html template)\n this._providerList = new ProviderList(this.config);\n const providerListElement = this._providerList.render(providers, (provider) => {\n this.handleProviderClick(provider);\n });\n\n container.appendChild(headerBar);\n container.appendChild(header);\n container.appendChild(providerListElement);\n\n return container;\n }\n\n /**\n * Handle provider click\n */\n private handleProviderClick(provider: Provider): void {\n debugLog(this.config, 'Provider clicked:', provider.id);\n\n // Update state\n this.stateManager.setState({ selectedProvider: provider });\n\n // Get session token\n const sessionToken = this.stateManager.get('sessionToken');\n if (!sessionToken) {\n const error = this.createError('no_session', 'No active session');\n this.eventEmitter.emit('error', error);\n return;\n }\n\n // Build authorization URL\n const authorizationUrl = this.apiClient.buildAuthorizationURL(provider.id, sessionToken, this._baseURL);\n\n // Create OAuth handler\n this._oauthHandler = new OAuthHandler({\n onSuccess: (connection: Connection) => {\n debugLog(this.config, 'OAuth success:', connection);\n this.handleOAuthSuccess(connection);\n },\n onError: (error: AlterError) => {\n debugLog(this.config, 'OAuth error:', error);\n this.handleOAuthError(error);\n },\n onCancel: () => {\n debugLog(this.config, 'OAuth cancelled');\n this.handleOAuthCancel();\n },\n popupWidth: 450,\n popupHeight: 600,\n debug: this.config.debug,\n });\n\n // Open OAuth popup\n this._oauthHandler.openPopup(authorizationUrl);\n\n debugLog(this.config, 'OAuth flow started for provider:', provider.id);\n }\n\n /**\n * Handle OAuth success\n */\n private handleOAuthSuccess(connection: Connection): void {\n // Update state\n this.stateManager.setState({\n selectedProvider: null,\n });\n\n // Emit success event\n this.eventEmitter.emit('success', connection);\n\n // Clean up OAuth handler\n if (this._oauthHandler) {\n this._oauthHandler = null;\n }\n }\n\n /**\n * Handle OAuth error\n */\n private handleOAuthError(error: AlterError): void {\n // Update state\n this.stateManager.setState({\n selectedProvider: null,\n error,\n });\n\n // Emit error event\n this.eventEmitter.emit('error', error);\n\n // Clean up OAuth handler\n if (this._oauthHandler) {\n this._oauthHandler = null;\n }\n }\n\n /**\n * Handle OAuth cancellation\n */\n private handleOAuthCancel(): void {\n // Update state\n this.stateManager.setState({\n selectedProvider: null,\n });\n\n // Emit exit event (user cancelled)\n this.eventEmitter.emit('exit');\n\n // Clean up OAuth handler\n if (this._oauthHandler) {\n this._oauthHandler = null;\n }\n }\n\n /**\n * Register event handlers from OpenOptions\n */\n private registerEventHandlers(options: OpenOptions): void {\n // Success handler\n if (options.onSuccess) {\n this.eventEmitter.on('success', (connection: Connection) => {\n options.onSuccess(connection);\n this.close();\n });\n }\n\n // Exit handler\n if (options.onExit) {\n this.eventEmitter.on('exit', () => {\n options.onExit!();\n this.close();\n });\n }\n\n // Error handler\n if (options.onError) {\n this.eventEmitter.on('error', (error: AlterError) => {\n options.onError!(error);\n });\n }\n\n // Event handler (analytics)\n if (options.onEvent) {\n this.eventEmitter.on('event', (eventName: string, metadata: any) => {\n options.onEvent!(eventName, metadata);\n });\n }\n }\n\n /**\n * Create an AlterError object\n */\n private createError(code: string, message: string, details?: Record<string, any>): Error {\n const error = new Error(message);\n (error as any).code = code;\n (error as any).details = details;\n return error;\n }\n\n /**\n * Normalize error to AlterError format\n */\n private normalizeError(error: any): AlterError {\n if (error && typeof error === 'object' && 'code' in error && 'message' in error) {\n return error as AlterError;\n }\n\n const err = this.createError(\n 'unknown_error',\n error?.message || String(error) || 'An unexpected error occurred',\n { originalError: error }\n );\n\n return {\n code: (err as any).code,\n message: err.message,\n details: (err as any).details,\n };\n }\n}\n"],"names":["DEFAULT_CONFIG","colors","primary","text","background","fontFamily","validateConfig","config","customization","isValidColor","Error","mergeConfig","defaultColors","defaultFont","locale","debug","debugLog","args","console","log","color","test","toLowerCase","EventEmitter","constructor","this","events","Map","on","event","handler","has","set","Set","get","add","off","handlers","delete","emit","forEach","error","removeAllListeners","clear","StateManager","state","isOpen","isLoading","sessionToken","providers","selectedProvider","searchQuery","categoryFilter","listeners","getState","key","setState","updates","notifyListeners","subscribe","listener","clearListeners","currentState","AlterAPIClient","TIMEOUT","DEFAULT_BASE_URL","fetchProviders","baseURL","response","fetch","method","length","fetchBranding","buildAuthorizationURL","providerId","url","endpoint","options","headers","controller","AbortController","timeoutId","setTimeout","abort","body","signal","clearTimeout","ok","errorData","json","catch","message","status","statusText","createError","error_description","name","timeout","TypeError","originalError","isAlterError","code","details","Modal","overlay","container","contentEl","closeButton","onClose","handleClose","handleEscape","e","open","document","createElement","className","style","cssText","innerHTML","setAttribute","addEventListener","backgroundColor","appendChild","target","overflow","setContent","content","close","parentNode","removeChild","removeEventListener","destroy","ProviderList","onProviderClick","render","renderProviders","update","emptyState","textContent","provider","button","createProviderButton","id","arrow","borderColor","boxShadow","transform","iconContainer","logo_url","logoImg","src","alt","charAt","toUpperCase","infoContainer","category","slice","OAuthHandler","popup","pollInterval","messageListener","onSuccess","onError","onCancel","popupWidth","popupHeight","openPopup","left","window","screenX","outerWidth","top","screenY","outerHeight","features","join","startPolling","setupMessageListener","closed","clearInterval","setInterval","data","type","connection","connection_id","provider_name","account_identifier","timestamp","operation","scopes","metadata","VERSION","AlterConnect","_searchBar","_providerList","_oauthHandler","_baseURL","eventEmitter","stateManager","apiClient","_modal","_isInitialized","getElementById","head","injectGlobalStyles","version","create","token","branding","Promise","all","font_family","logoUrl","undefined","registerEventHandlers","handleProviderClick","onEvent","Date","toISOString","buildUIContent","providerCount","normalizeError","updateConfig","newConfig","getConfig","getVersion","headerBar","logo","textLogo","replaceWith","header","title","subtitle","providerListElement","authorizationUrl","handleOAuthSuccess","handleOAuthError","handleOAuthCancel","onExit","eventName","err","String"],"mappings":"4OA0BA,MAAMA,EACW,CACbC,OAAQ,CACNC,QAAS,UACTC,KAAM,UACNC,WAAY,WAEdC,WAAY,8FAPVL,EASI,KATJA,GAUG,EAMH,SAAUM,EAAeC,GAC7B,GAAIA,EAAOC,eAAeP,QAAQC,UAC3BO,EAAaF,EAAOC,cAAcP,OAAOC,SAC5C,MAAM,IAAIQ,MAAM,0BAA0BH,EAAOC,cAAcP,OAAOC,WAI1E,GAAIK,EAAOC,eAAeP,QAAQE,OAC3BM,EAAaF,EAAOC,cAAcP,OAAOE,MAC5C,MAAM,IAAIO,MAAM,uBAAuBH,EAAOC,cAAcP,OAAOE,QAIvE,GAAII,EAAOC,eAAeP,QAAQG,aAC3BK,EAAaF,EAAOC,cAAcP,OAAOG,YAC5C,MAAM,IAAIM,MAAM,6BAA6BH,EAAOC,cAAcP,OAAOG,aAG/E,CAKM,SAAUO,EAAYJ,GAC1B,MAAMK,EAAgBZ,EAA6BC,OAC7CY,EAAcb,EAA6BK,WAEjD,MAAO,CACLG,cAAe,CACbP,OAAQ,CACNC,QAASK,EAAOC,eAAeP,QAAQC,SAAWU,EAAcV,QAChEC,KAAMI,EAAOC,eAAeP,QAAQE,MAAQS,EAAcT,KAC1DC,WAAYG,EAAOC,eAAeP,QAAQG,YAAcQ,EAAcR,YAExEC,WAAYE,EAAOC,eAAeH,YAAcQ,GAElDC,OAAQP,EAAOO,QAAUd,EACzBe,MAAOR,EAAOQ,OAASf,EAE3B,UAKgBgB,EAAST,KAAuBU,GAC1CV,EAAOQ,OACTG,QAAQC,IAAI,qBAAsBF,EAEtC,CAUA,SAASR,EAAaW,GAEpB,QAAI,qCAAqCC,KAAKD,OAK1C,2DAA2DC,KAAKD,OAKhE,mEAAmEC,KAAKD,MAKxE,WAAWC,KAAKD,EAAME,gBAK5B,OCjHaC,EAGX,WAAAC,GACEC,KAAKC,OAAS,IAAIC,GACpB,CAMA,EAAAC,CAAGC,EAAeC,GAQhB,OAPKL,KAAKC,OAAOK,IAAIF,IACnBJ,KAAKC,OAAOM,IAAIH,EAAO,IAAII,KAG7BR,KAAKC,OAAOQ,IAAIL,GAAQM,IAAIL,GAGrB,IAAML,KAAKW,IAAIP,EAAOC,EAC/B,CAKA,GAAAM,CAAIP,EAAeC,GACjB,MAAMO,EAAWZ,KAAKC,OAAOQ,IAAIL,GAC7BQ,GACFA,EAASC,OAAOR,EAEpB,CAKA,IAAAS,CAAKV,KAAkBZ,GACrB,MAAMoB,EAAWZ,KAAKC,OAAOQ,IAAIL,GAC7BQ,GACFA,EAASG,QAAQV,IACf,IACEA,KAAWb,EACb,CAAE,MAAOwB,GACPvB,QAAQuB,MAAM,+CAA+CZ,MAAWY,EAC1E,GAGN,CAKA,kBAAAC,CAAmBb,GACbA,EACFJ,KAAKC,OAAOY,OAAOT,GAEnBJ,KAAKC,OAAOiB,OAEhB,QCzCWC,EAIX,WAAApB,GACEC,KAAKoB,MAAQ,CACXC,QAAQ,EACRC,WAAW,EACXN,MAAO,KACPO,aAAc,KACdC,UAAW,GACXC,iBAAkB,KAClBC,YAAa,GACbC,eAAgB,MAElB3B,KAAK4B,UAAY,IAAIpB,GACvB,CAKA,QAAAqB,GACE,MAAO,IAAK7B,KAAKoB,MACnB,CAKA,GAAAX,CAA8BqB,GAC5B,OAAO9B,KAAKoB,MAAMU,EACpB,CAKA,QAAAC,CAASC,GACPhC,KAAKoB,MAAQ,IAAKpB,KAAKoB,SAAUY,GACjChC,KAAKiC,iBACP,CAKA,SAAAC,CAAUC,GAIR,OAHAnC,KAAK4B,UAAUlB,IAAIyB,GAGZ,KACLnC,KAAK4B,UAAUf,OAAOsB,GAE1B,CAKA,cAAAC,GACEpC,KAAK4B,UAAUV,OACjB,CAKQ,eAAAe,GACN,MAAMI,EAAerC,KAAK6B,WAC1B7B,KAAK4B,UAAUb,QAAQoB,IACrB,IACEA,EAASE,EACX,CAAE,MAAOrB,GACPvB,QAAQuB,MAAM,2CAA4CA,EAC5D,GAEJ,QCtFWsB,EAKX,WAAAvC,CAAYT,GAAiB,GAHZU,KAAAuC,QAAU,IACVvC,KAAAwC,iBAAmB,0BAGlCxC,KAAKV,MAAQA,CACf,CAKA,oBAAMmD,CAAelB,EAAsBmB,GACzC1C,KAAKN,IAAI,yCAET,MAAMiD,QAAiB3C,KAAK4C,MAAiC,mBAAoB,CAC/EC,OAAQ,MACRtB,eACAmB,QAASA,GAAW1C,KAAKwC,mBAI3B,OADAxC,KAAKN,IAAI,WAAWiD,EAASnB,UAAUsB,oBAChCH,EAASnB,SAClB,CAKA,mBAAMuB,CAAcxB,EAAsBmB,GACxC1C,KAAKN,IAAI,wCAET,MAAMiD,QAAiB3C,KAAK4C,MAAW,kBAAmB,CACxDC,OAAQ,MACRtB,eACAmB,QAASA,GAAW1C,KAAKwC,mBAI3B,OADAxC,KAAKN,IAAI,oBAAqBiD,GACvBA,CACT,CAKA,qBAAAK,CAAsBC,EAAoB1B,EAAsBmB,GAC9D,MACMQ,EAAM,GADCR,GAAW1C,KAAKwC,oDAC0BS,aAAsB1B,IAE7E,OADAvB,KAAKN,IAAI,qBAAsBwD,GACxBA,CACT,CAKQ,WAAMN,CACZO,EACAC,GAOA,MAAMF,EAAM,GAAGE,EAAQV,UAAUS,IAE3BE,EAAkC,CACtC,eAAgB,oBAIdD,EAAQ7B,eACV8B,EAAQ,mBAAqBD,EAAQ7B,cAGvC,MAAM+B,EAAa,IAAIC,gBACjBC,EAAYC,WAAW,IAAMH,EAAWI,QAAS1D,KAAKuC,SAE5D,IACE,MAAMI,QAAiBC,MAAMM,EAAK,CAChCL,OAAQO,EAAQP,OAChBQ,UACAM,KAAMP,EAAQO,KACdC,OAAQN,EAAWM,SAKrB,GAFAC,aAAaL,IAERb,EAASmB,GAAI,CAChB,MAAMC,QAAkBpB,EAASqB,OAAOC,MAAM,KAAA,CAC5CjD,MAAO,gBACPkD,QAAS,QAAQvB,EAASwB,WAAWxB,EAASyB,gBAGhD,MAAMpE,KAAKqE,YACTN,EAAU/C,OAAS,YACnB+C,EAAUG,SAAWH,EAAUO,mBAAqB,8BAA8B3B,EAASwB,SAC3FJ,EAEJ,CAEA,aAAapB,EAASqB,MACxB,CAAE,MAAOhD,GAIP,GAHA6C,aAAaL,GAGM,eAAfxC,EAAMuD,KACR,MAAMvE,KAAKqE,YACT,UACA,2BAA2BrE,KAAKuC,YAChC,CAAEiC,QAASxE,KAAKuC,UAKpB,GAAIvB,aAAiByD,UACnB,MAAMzE,KAAKqE,YACT,gBACA,iEACA,CAAEK,cAAe1D,EAAMkD,UAK3B,GAAIlE,KAAK2E,aAAa3D,GACpB,MAAMA,EAIR,MAAMhB,KAAKqE,YAAY,gBAAiBrD,EAAMkD,SAAW,+BAAgC,CACvFQ,cAAe1D,GAEnB,CACF,CAKQ,WAAAqD,CAAYO,EAAcV,EAAiBW,GACjD,MAAO,CACLD,OACAV,UACAW,UAEJ,CAKQ,YAAAF,CAAa3D,GACnB,OAAOA,GAA0B,iBAAVA,GAAsB,SAAUA,GAAS,YAAaA,CAC/E,CAKQ,GAAAtB,IAAOF,GACTQ,KAAKV,OACPG,QAAQC,IAAI,wBAAyBF,EAEzC,QC5JWsF,EAQX,WAAA/E,CAAYjB,GAPJkB,KAAA+E,QAA8B,KAC9B/E,KAAAgF,UAAgC,KAChChF,KAAAiF,UAAgC,KAChCjF,KAAAkF,YAAkC,KAElClF,KAAAmF,QAA+B,KA4J/BnF,KAAAoF,YAAc,KAChBpF,KAAKmF,SACPnF,KAAKmF,WAODnF,KAAAqF,aAAgBC,IACR,WAAVA,EAAExD,KACJ9B,KAAKoF,eApKPpF,KAAKlB,OAASA,CAChB,CAKA,IAAAyG,CAAKnC,GACHpD,KAAKmF,QAAU/B,EAAQ+B,QAGvBnF,KAAK+E,QAAUS,SAASC,cAAc,OACtCzF,KAAK+E,QAAQW,UAAY,wBACzB1F,KAAK+E,QAAQY,MAAMC,QAAU,iTAe7B5F,KAAKgF,UAAYQ,SAASC,cAAc,OACxCzF,KAAKgF,UAAUU,UAAY,sBAC3B1F,KAAKgF,UAAUW,MAAMC,QAAU,iUAUd5F,KAAKlB,OAAOC,cAAcH,mGAM3CoB,KAAKkF,YAAcM,SAASC,cAAc,UAC1CzF,KAAKkF,YAAYQ,UAAY,sBAC7B1F,KAAKkF,YAAYW,UAAY,UAC7B7F,KAAKkF,YAAYY,aAAa,aAAc,SAC5C9F,KAAKkF,YAAYS,MAAMC,QAAU,4bAmBjC5F,KAAKkF,YAAYa,iBAAiB,QAAS,IAAM/F,KAAKoF,eACtDpF,KAAKkF,YAAYa,iBAAiB,aAAc,KAC9C/F,KAAKkF,YAAaS,MAAMK,gBAAkB,UAC1ChG,KAAKkF,YAAaS,MAAMhG,MAAQ,YAElCK,KAAKkF,YAAYa,iBAAiB,aAAc,KAC9C/F,KAAKkF,YAAaS,MAAMK,gBAAkB,cAC1ChG,KAAKkF,YAAaS,MAAMhG,MAAQ,YAIlCK,KAAKiF,UAAYO,SAASC,cAAc,OACxCzF,KAAKiF,UAAUS,UAAY,wBAC3B1F,KAAKiF,UAAUU,MAAMC,QAAU,kHAQ/B5F,KAAKgF,UAAUiB,YAAYjG,KAAKkF,aAChClF,KAAKgF,UAAUiB,YAAYjG,KAAKiF,WAChCjF,KAAK+E,QAAQkB,YAAYjG,KAAKgF,WAG9BQ,SAAS7B,KAAKsC,YAAYjG,KAAK+E,SAG/B/E,KAAK+E,QAAQgB,iBAAiB,QAAUT,IAClCA,EAAEY,SAAWlG,KAAK+E,SACpB/E,KAAKoF,gBAKTI,SAASO,iBAAiB,UAAW/F,KAAKqF,cAG1CG,SAAS7B,KAAKgC,MAAMQ,SAAW,QACjC,CAKA,UAAAC,CAAWC,GACLrG,KAAKiF,YACPjF,KAAKiF,UAAUY,UAAY,GAC3B7F,KAAKiF,UAAUgB,YAAYI,GAE/B,CAKA,KAAAC,GAEMtG,KAAK+E,SAAW/E,KAAK+E,QAAQwB,YAC/BvG,KAAK+E,QAAQwB,WAAWC,YAAYxG,KAAK+E,SAI3C/E,KAAK+E,QAAU,KACf/E,KAAKgF,UAAY,KACjBhF,KAAKiF,UAAY,KACjBjF,KAAKkF,YAAc,KACnBlF,KAAKmF,QAAU,KAGfK,SAASiB,oBAAoB,UAAWzG,KAAKqF,cAG7CG,SAAS7B,KAAKgC,MAAMQ,SAAW,EACjC,CAKA,OAAAO,GACE1G,KAAKsG,OACP,QC9JWK,EAKX,WAAA5G,CAAYjB,GAJJkB,KAAAgF,UAAgC,KAEhChF,KAAA4G,gBAA+C,KAGrD5G,KAAKlB,OAASA,CAChB,CAKA,MAAA+H,CAAOrF,EAAuBoF,GAgB5B,OAfA5G,KAAK4G,gBAAkBA,EAGvB5G,KAAKgF,UAAYQ,SAASC,cAAc,OACxCzF,KAAKgF,UAAUU,UAAY,8BAC3B1F,KAAKgF,UAAUW,MAAMC,QAAU,kJAQ/B5F,KAAK8G,gBAAgBtF,GAEdxB,KAAKgF,SACd,CAKA,MAAA+B,CAAOvF,GACDxB,KAAKgF,YACPhF,KAAKgF,UAAUa,UAAY,GAC3B7F,KAAK8G,gBAAgBtF,GAEzB,CAKA,OAAAkF,GACE1G,KAAKgF,UAAY,KACjBhF,KAAK4G,gBAAkB,IACzB,CAKQ,eAAAE,CAAgBtF,GACtB,GAAKxB,KAAKgF,UAAV,CAEA,GAAyB,IAArBxD,EAAUsB,OAAc,CAE1B,MAAMkE,EAAaxB,SAASC,cAAc,OAS1C,OARAuB,EAAWrB,MAAMC,QAAU,sHAM3BoB,EAAWC,YAAc,0BACzBjH,KAAKgF,UAAUiB,YAAYe,EAE7B,CAEAxF,EAAUT,QAAQmG,IAChB,MAAMC,EAASnH,KAAKoH,qBAAqBF,GACzClH,KAAKgF,UAAWiB,YAAYkB,IAlBT,CAoBvB,CAKQ,oBAAAC,CAAqBF,GAE3B,MAAMC,EAAS3B,SAASC,cAAc,UACtC0B,EAAOzB,UAAY,gCACnByB,EAAOrB,aAAa,mBAAoBoB,EAASG,IACjDF,EAAOxB,MAAMC,QAAU,oTAYN5F,KAAKlB,OAAOC,cAAcH,wCAK3C,MAAM0I,EAAQ9B,SAASC,cAAc,QACrC6B,EAAML,YAAc,IACpBK,EAAM5B,UAAY,gBAClB4B,EAAM3B,MAAMC,QAAU,6GAQtBuB,EAAOpB,iBAAiB,aAAc,KACpCoB,EAAOxB,MAAM4B,YAAc,UAC3BJ,EAAOxB,MAAM6B,UAAY,gCACzBL,EAAOxB,MAAM8B,UAAY,mBACzBH,EAAM3B,MAAMhG,MAAQ,UACpB2H,EAAM3B,MAAM8B,UAAY,oBAG1BN,EAAOpB,iBAAiB,aAAc,KACpCoB,EAAOxB,MAAM4B,YAAc,UAC3BJ,EAAOxB,MAAM6B,UAAY,OACzBL,EAAOxB,MAAM8B,UAAY,gBACzBH,EAAM3B,MAAMhG,MAAQ,UACpB2H,EAAM3B,MAAM8B,UAAY,kBAI1B,MAAMC,EAAgBlC,SAASC,cAAc,OAc7C,GAbAiC,EAAc/B,MAAMC,QAAU,oPAa1BsB,EAASS,SAAU,CACrB,MAAMC,EAAUpC,SAASC,cAAc,OACvCmC,EAAQC,IAAMX,EAASS,SACvBC,EAAQE,IAAMZ,EAAS3C,KACvBqD,EAAQjC,MAAMC,QAAU,sFAOxBgC,EAAQ7B,iBAAiB,QAAS,KAChC2B,EAAcT,YAAcC,EAAS3C,KAAKwD,OAAO,GAAGC,gBAGtDN,EAAczB,YAAY2B,EAC5B,MAEEF,EAAcT,YAAcC,EAAS3C,KAAKwD,OAAO,GAAGC,cAItD,MAAMC,EAAgBzC,SAASC,cAAc,OAC7CwC,EAActC,MAAMC,QAAU,uEAO9B,MAAMrB,EAAOiB,SAASC,cAAc,OACpClB,EAAK0C,YAAcC,EAAS3C,KAC5BA,EAAKoB,MAAMC,QAAU,iMAWrB,MAAMsC,EAAW1C,SAASC,cAAc,OAuBxC,OAtBAyC,EAASjB,YAAcC,EAASgB,SAAWhB,EAASgB,SAASH,OAAO,GAAGC,cAAgBd,EAASgB,SAASC,MAAM,GAAK,QACpHD,EAASvC,MAAMC,QAAU,iFAMzBqC,EAAchC,YAAY1B,GAC1B0D,EAAchC,YAAYiC,GAG1Bf,EAAOlB,YAAYyB,GACnBP,EAAOlB,YAAYgC,GACnBd,EAAOlB,YAAYqB,GAGnBH,EAAOpB,iBAAiB,QAAS,KAC3B/F,KAAK4G,iBACP5G,KAAK4G,gBAAgBM,KAIlBC,CACT,QC3MWiB,EAMX,WAAArI,CAAYqD,GALJpD,KAAAqI,MAAuB,KACvBrI,KAAAsI,aAA8B,KAC9BtI,KAAAuI,gBAA0D,KAIhEvI,KAAKoD,QAAU,CACboF,UAAWpF,EAAQoF,UACnBC,QAASrF,EAAQqF,QACjBC,SAAUtF,EAAQsF,SAClBC,WAAYvF,EAAQuF,YAAc,IAClCC,YAAaxF,EAAQwF,aAAe,IACpCtJ,MAAO8D,EAAQ9D,QAAS,EAE5B,CAKA,SAAAuJ,CAAU3F,GAER,MAAM4F,EAAOC,OAAOC,SAAWD,OAAOE,WAAajJ,KAAKoD,QAAQuF,YAAc,EACxEO,EAAMH,OAAOI,SAAWJ,OAAOK,YAAcpJ,KAAKoD,QAAQwF,aAAe,EAEzES,EAAW,CACf,SAASrJ,KAAKoD,QAAQuF,aACtB,UAAU3I,KAAKoD,QAAQwF,cACvB,QAAQE,IACR,OAAOI,IACP,gBACA,iBACA,cACAI,KAAK,KAEPtJ,KAAKN,IAAI,uBAAwBwD,GAGjClD,KAAKqI,MAAQU,OAAOxD,KAAKrC,EAAK,oBAAqBmG,GAE9CrJ,KAAKqI,OASVrI,KAAKuJ,eACLvJ,KAAKwJ,wBATHxJ,KAAKoD,QAAQqF,QAAQ,CACnB7D,KAAM,gBACNV,QAAS,oEAQf,CAKA,KAAAoC,GACEtG,KAAKN,IAAI,yBAGLM,KAAKqI,QAAUrI,KAAKqI,MAAMoB,QAC5BzJ,KAAKqI,MAAM/B,QAEbtG,KAAKqI,MAAQ,KAGa,OAAtBrI,KAAKsI,eACPoB,cAAc1J,KAAKsI,cACnBtI,KAAKsI,aAAe,MAIlBtI,KAAKuI,kBACPQ,OAAOtC,oBAAoB,UAAWzG,KAAKuI,iBAC3CvI,KAAKuI,gBAAkB,KAE3B,CAKQ,YAAAgB,GACNvJ,KAAKsI,aAAeS,OAAOY,YAAY,KAChC3J,KAAKqI,QAASrI,KAAKqI,MAAMoB,SAC5BzJ,KAAKN,IAAI,wBACTM,KAAKsG,QACLtG,KAAKoD,QAAQsF,aAEd,IACL,CAKQ,oBAAAc,GACNxJ,KAAKuI,gBAAmBnI,IAGtBJ,KAAKN,IAAI,oBAAqBU,EAAMwJ,MAEpC,MAAMA,EAAOxJ,EAAMwJ,KAGnB,GAAIA,GAAwB,iBAATA,EACjB,GAAkB,0BAAdA,EAAKC,KAAkC,CACzC7J,KAAKN,IAAI,iBAET,MAAMoK,EAAyB,CAC7BC,cAAeH,EAAKG,cACpB7C,SAAU0C,EAAK1C,SACf8C,cAAeJ,EAAKI,eAAiBJ,EAAK1C,SAC1C+C,mBAAoBL,EAAKK,mBACzBC,UAAWN,EAAKM,UAChBC,UAAWP,EAAKO,WAAa,WAC7BC,OAAQR,EAAKQ,QAAU,GACvBjG,OAAQyF,EAAKzF,QAAU,SACvBkG,SAAUT,EAAKS,UAGjBrK,KAAKsG,QACLtG,KAAKoD,QAAQoF,UAAUsB,EACzB,MAAO,GAAkB,wBAAdF,EAAKC,KAAgC,CAC9C7J,KAAKN,IAAI,eAET,MAAMsB,EAAoB,CACxB4D,KAAMgF,EAAK5I,OAAS,cACpBkD,QAAS0F,EAAKtF,mBAAqB,6BACnCO,QAAS+E,GAGX5J,KAAKsG,QACLtG,KAAKoD,QAAQqF,QAAQzH,EACvB,GAIJ+H,OAAOhD,iBAAiB,UAAW/F,KAAKuI,gBAC1C,CAKQ,GAAA7I,IAAOF,GACTQ,KAAKoD,QAAQ9D,OACfG,QAAQC,IAAI,qBAAsBF,EAEtC,ECnJF,MAAM8K,EAAU,cAKHC,EAeX,WAAAxK,CAAoBjB,EAA6B,IARzCkB,KAAAwK,WAA+B,KAC/BxK,KAAAyK,cAAqC,KACrCzK,KAAA0K,cAAqC,KACrC1K,KAAA2K,SAAmB,0BAOzB9L,EAAeC,GACfkB,KAAKlB,OAASI,EAAYJ,GAG1BkB,KAAK4K,aAAe,IAAI9K,EACxBE,KAAK6K,aAAe,IAAI1J,EACxBnB,KAAK8K,UAAY,IAAIxI,EAAetC,KAAKlB,OAAOQ,OAChDU,KAAK+K,OAAS,IAAIjG,EAAM9E,KAAKlB,QAC7BkB,KAAKgL,gBAAiB,aHqJxB,GAAIxF,SAASyF,eAAe,wBAC1B,OAGF,MAAMtF,EAAQH,SAASC,cAAc,SACrCE,EAAM0B,GAAK,uBACX1B,EAAMsB,YAAc,mYAsBpBzB,SAAS0F,KAAKjF,YAAYN,EAC5B,CG/KIwF,GAEA5L,EAASS,KAAKlB,OAAQ,gCAAiC,CAAEsM,QAASd,GACpE,CAqBA,aAAOe,CAAOvM,GACZ,OAAO,IAAIyL,EAAazL,EAC1B,CAuBA,UAAMyG,CAAKnC,GAET,IAAKpD,KAAKgL,eACR,MAAMhL,KAAKqE,YAAY,gBAAiB,wDAM1C,GAHA9E,EAASS,KAAKlB,OAAQ,uBAGjBsE,EAAQkI,OAAkC,iBAAlBlI,EAAQkI,MACnC,MAAMtL,KAAKqE,YAAY,kBAAmB,6FAG5C,IAAKjB,EAAQoF,WAA0C,mBAAtBpF,EAAQoF,UACvC,MAAMxI,KAAKqE,YAAY,kBAAmB,kCAI5C,GAAIrE,KAAKqB,SACP9B,EAASS,KAAKlB,OAAQ,mCAIxB,IAEEkB,KAAK2K,SAAWvH,EAAQV,SAAW,0BAGnC1C,KAAK6K,aAAa9I,SAAS,CAAEV,QAAQ,EAAMC,WAAW,EAAMN,MAAO,OACnEhB,KAAK6K,aAAa9I,SAAS,CAAER,aAAc6B,EAAQkI,QAGnD,MAAO9J,EAAW+J,SAAkBC,QAAQC,IAAI,CAC9CzL,KAAK8K,UAAUrI,eAAeW,EAAQkI,MAAOtL,KAAK2K,UAClD3K,KAAK8K,UAAU/H,cAAcK,EAAQkI,MAAOtL,KAAK2K,UAAU1G,MAAM,IAAM,QAkCzE,GA9BIsH,IACFhM,EAASS,KAAKlB,OAAQ,8BAGlByM,EAAS/M,SACXwB,KAAKlB,OAAOC,cAAcP,OAAS,CACjCC,QAAS8M,EAAS/M,OAAOC,QACzBC,KAAM6M,EAAS/M,OAAOE,KACtBC,WAAY4M,EAAS/M,OAAOG,aAK5B4M,EAASG,cACX1L,KAAKlB,OAAOC,cAAcH,WAAa2M,EAASG,aAIlD1L,KAAKlB,OAAOC,cAAc4M,QAAUJ,EAAS5D,eAAYiE,GAG3D5L,KAAK6K,aAAa9I,SAAS,CACzBP,YACAF,WAAW,IAIbtB,KAAK6L,sBAAsBzI,GAGF,IAArB5B,EAAUsB,OACZvD,EAASS,KAAKlB,OAAQ,oDAGtBkB,KAAK8L,oBAAoBtK,EAAU,IAG/B4B,EAAQ2I,SACV3I,EAAQ2I,QAAQ,uBAAwB,CACtC7B,WAAW,IAAI8B,MAAOC,cACtB/E,SAAU1F,EAAU,GAAG6F,SAGtB,CACL9H,EAASS,KAAKlB,OAAQ,sDAGtB,MAAMuH,EAAUrG,KAAKkM,eAAe1K,GAGpCxB,KAAK+K,OAAOxF,KAAK,CACfJ,QAAS,KACPnF,KAAK4K,aAAa9J,KAAK,WAG3Bd,KAAK+K,OAAO3E,WAAWC,GAGnBjD,EAAQ2I,SACV3I,EAAQ2I,QAAQ,eAAgB,CAC9B7B,WAAW,IAAI8B,MAAOC,cACtBE,cAAe3K,EAAUsB,QAG/B,CAEAvD,EAASS,KAAKlB,OAAQ,iCACxB,CAAE,MAAOkC,GAaP,MAZAzB,EAASS,KAAKlB,OAAQ,4BAA6BkC,GAEnDhB,KAAK6K,aAAa9I,SAAS,CACzBT,WAAW,EACXD,QAAQ,EACRL,MAAOhB,KAAKoM,eAAepL,KAGzBoC,EAAQqF,SACVrF,EAAQqF,QAAQzI,KAAKoM,eAAepL,IAGhCA,CACR,CACF,CAKA,KAAAsF,GAEE,IAAKtG,KAAKgL,eACR,MAAMhL,KAAKqE,YAAY,gBAAiB,yDAG1C9E,EAASS,KAAKlB,OAAQ,sBAGlBkB,KAAK0K,gBACP1K,KAAK0K,cAAcpE,QACnBtG,KAAK0K,cAAgB,MAInB1K,KAAKwK,aACPxK,KAAKwK,WAAW9D,UAChB1G,KAAKwK,WAAa,MAGhBxK,KAAKyK,gBACPzK,KAAKyK,cAAc/D,UACnB1G,KAAKyK,cAAgB,MAIvBzK,KAAK+K,OAAOzE,QAGZtG,KAAK6K,aAAa9I,SAAS,CACzBV,QAAQ,EACRI,iBAAkB,KAClBC,YAAa,GACbC,eAAgB,OAGlB3B,KAAK4K,aAAa9J,KAAK,QACzB,CAKA,OAAA4F,GACO1G,KAAKgL,iBAKVzL,EAASS,KAAKlB,OAAQ,2BAGlBkB,KAAK0K,gBACP1K,KAAK0K,cAAcpE,QACnBtG,KAAK0K,cAAgB,MAInB1K,KAAKwK,aACPxK,KAAKwK,WAAW9D,UAChB1G,KAAKwK,WAAa,MAGhBxK,KAAKyK,gBACPzK,KAAKyK,cAAc/D,UACnB1G,KAAKyK,cAAgB,MAIvBzK,KAAK+K,OAAOrE,UAGR1G,KAAK6K,aAAapK,IAAI,WACxBT,KAAK6K,aAAa9I,SAAS,CACzBV,QAAQ,EACRI,iBAAkB,KAClBC,YAAa,GACbC,eAAgB,OAKpB3B,KAAK4K,aAAa3J,qBAClBjB,KAAK6K,aAAazI,iBAClBpC,KAAKgL,gBAAiB,EACxB,CAKA,YAAAqB,CAAavN,GAEX,IAAKkB,KAAKgL,eACR,MAAMhL,KAAKqE,YAAY,gBAAiB,gEAG1C9E,EAASS,KAAKlB,OAAQ,kBAAmBA,GAEzC,MAAMwN,EAAY,IAAKtM,KAAKlB,UAAWA,GACvCD,EAAeyN,GACftM,KAAKlB,OAASI,EAAYoN,GAG1BtM,KAAK8K,UAAY,IAAIxI,EAAetC,KAAKlB,OAAOQ,MAClD,CAKA,SAAAiN,GACE,MAAO,IAAKvM,KAAKlB,OACnB,CAKA,EAAAqB,CAAGC,EAAeC,GAEhB,IAAKL,KAAKgL,eACR,MAAMhL,KAAKqE,YAAY,gBAAiB,sDAG1C,OAAOrE,KAAK4K,aAAazK,GAAGC,EAAOC,EACrC,CAKA,GAAAM,CAAIP,EAAeC,GAEjB,IAAKL,KAAKgL,eACR,MAAMhL,KAAKqE,YAAY,gBAAiB,uDAG1CrE,KAAK4K,aAAajK,IAAIP,EAAOC,EAC/B,CAKA,MAAAgB,GAEE,IAAKrB,KAAKgL,eACR,MAAMhL,KAAKqE,YAAY,gBAAiB,0DAG1C,OAAOrE,KAAK6K,aAAapK,IAAI,SAC/B,CAKA,UAAA+L,GACE,OAAOlC,CACT,CAKQ,cAAA4B,CAAe1K,GACrB,MAAMwD,EAAYQ,SAASC,cAAc,OACzCT,EAAUU,UAAY,6BAGtB,MAAM+G,EAAYjH,SAASC,cAAc,OACzCgH,EAAU9G,MAAMC,QAAU,kOAW1B,MAAM8G,EAAOlH,SAASC,cAAc,OAEhCzF,KAAKlB,OAAOC,cAAc4M,SAC5Be,EAAK7E,IAAM7H,KAAKlB,OAAOC,cAAc4M,QACrCe,EAAK5E,IAAM,aAEX4E,EAAK7E,IAAM,GAAG7H,KAAK2K,8CACnB+B,EAAK5E,IAAM,SAGb4E,EAAK/G,MAAMC,QAAU,uGAQrB8G,EAAK3G,iBAAiB,QAAS,KAC7B,MAAM4G,EAAWnH,SAASC,cAAc,OACxCkH,EAAS1F,YAAc,QACvB0F,EAAShH,MAAMC,QAAU,6OAOzB8G,EAAKE,YAAYD,KAGnBF,EAAUxG,YAAYyG,GAGtB,MAAMG,EAASrH,SAASC,cAAc,OACtCoH,EAAOlH,MAAMC,QAAU,gEAKvB,MAAMkH,EAAQtH,SAASC,cAAc,MACrCqH,EAAM7F,YAAc,yBACpB6F,EAAMnH,MAAMC,QAAU,4PAStB,MAAMmH,EAAWvH,SAASC,cAAc,KACxCsH,EAAS9F,YAAc,8CACvB8F,EAASpH,MAAMC,QAAU,mNAQzBiH,EAAO5G,YAAY6G,GACnBD,EAAO5G,YAAY8G,GAGnB/M,KAAKyK,cAAgB,IAAI9D,EAAa3G,KAAKlB,QAC3C,MAAMkO,EAAsBhN,KAAKyK,cAAc5D,OAAOrF,EAAY0F,IAChElH,KAAK8L,oBAAoB5E,KAO3B,OAJAlC,EAAUiB,YAAYwG,GACtBzH,EAAUiB,YAAY4G,GACtB7H,EAAUiB,YAAY+G,GAEfhI,CACT,CAKQ,mBAAA8G,CAAoB5E,GAC1B3H,EAASS,KAAKlB,OAAQ,oBAAqBoI,EAASG,IAGpDrH,KAAK6K,aAAa9I,SAAS,CAAEN,iBAAkByF,IAG/C,MAAM3F,EAAevB,KAAK6K,aAAapK,IAAI,gBAC3C,IAAKc,EAAc,CACjB,MAAMP,EAAQhB,KAAKqE,YAAY,aAAc,qBAE7C,YADArE,KAAK4K,aAAa9J,KAAK,QAASE,EAElC,CAGA,MAAMiM,EAAmBjN,KAAK8K,UAAU9H,sBAAsBkE,EAASG,GAAI9F,EAAcvB,KAAK2K,UAG9F3K,KAAK0K,cAAgB,IAAItC,EAAa,CACpCI,UAAYsB,IACVvK,EAASS,KAAKlB,OAAQ,iBAAkBgL,GACxC9J,KAAKkN,mBAAmBpD,IAE1BrB,QAAUzH,IACRzB,EAASS,KAAKlB,OAAQ,eAAgBkC,GACtChB,KAAKmN,iBAAiBnM,IAExB0H,SAAU,KACRnJ,EAASS,KAAKlB,OAAQ,mBACtBkB,KAAKoN,qBAEPzE,WAAY,IACZC,YAAa,IACbtJ,MAAOU,KAAKlB,OAAOQ,QAIrBU,KAAK0K,cAAc7B,UAAUoE,GAE7B1N,EAASS,KAAKlB,OAAQ,mCAAoCoI,EAASG,GACrE,CAKQ,kBAAA6F,CAAmBpD,GAEzB9J,KAAK6K,aAAa9I,SAAS,CACzBN,iBAAkB,OAIpBzB,KAAK4K,aAAa9J,KAAK,UAAWgJ,GAG9B9J,KAAK0K,gBACP1K,KAAK0K,cAAgB,KAEzB,CAKQ,gBAAAyC,CAAiBnM,GAEvBhB,KAAK6K,aAAa9I,SAAS,CACzBN,iBAAkB,KAClBT,UAIFhB,KAAK4K,aAAa9J,KAAK,QAASE,GAG5BhB,KAAK0K,gBACP1K,KAAK0K,cAAgB,KAEzB,CAKQ,iBAAA0C,GAENpN,KAAK6K,aAAa9I,SAAS,CACzBN,iBAAkB,OAIpBzB,KAAK4K,aAAa9J,KAAK,QAGnBd,KAAK0K,gBACP1K,KAAK0K,cAAgB,KAEzB,CAKQ,qBAAAmB,CAAsBzI,GAExBA,EAAQoF,WACVxI,KAAK4K,aAAazK,GAAG,UAAY2J,IAC/B1G,EAAQoF,UAAUsB,GAClB9J,KAAKsG,UAKLlD,EAAQiK,QACVrN,KAAK4K,aAAazK,GAAG,OAAQ,KAC3BiD,EAAQiK,SACRrN,KAAKsG,UAKLlD,EAAQqF,SACVzI,KAAK4K,aAAazK,GAAG,QAAUa,IAC7BoC,EAAQqF,QAASzH,KAKjBoC,EAAQ2I,SACV/L,KAAK4K,aAAazK,GAAG,QAAS,CAACmN,EAAmBjD,KAChDjH,EAAQ2I,QAASuB,EAAWjD,IAGlC,CAKQ,WAAAhG,CAAYO,EAAcV,EAAiBW,GACjD,MAAM7D,EAAQ,IAAI/B,MAAMiF,GAGxB,OAFClD,EAAc4D,KAAOA,EACrB5D,EAAc6D,QAAUA,EAClB7D,CACT,CAKQ,cAAAoL,CAAepL,GACrB,GAAIA,GAA0B,iBAAVA,GAAsB,SAAUA,GAAS,YAAaA,EACxE,OAAOA,EAGT,MAAMuM,EAAMvN,KAAKqE,YACf,gBACArD,GAAOkD,SAAWsJ,OAAOxM,IAAU,+BACnC,CAAE0D,cAAe1D,IAGnB,MAAO,CACL4D,KAAO2I,EAAY3I,KACnBV,QAASqJ,EAAIrJ,QACbW,QAAU0I,EAAY1I,QAE1B"}
@@ -0,0 +1,15 @@
1
+ import type { Provider } from '../types';
2
+ export declare class AlterAPIClient {
3
+ private debug;
4
+ private readonly TIMEOUT;
5
+ private readonly DEFAULT_BASE_URL;
6
+ constructor(debug?: boolean);
7
+ fetchProviders(sessionToken: string, baseURL?: string): Promise<Provider[]>;
8
+ fetchBranding(sessionToken: string, baseURL?: string): Promise<any>;
9
+ buildAuthorizationURL(providerId: string, sessionToken: string, baseURL?: string): string;
10
+ private fetch;
11
+ private createError;
12
+ private isAlterError;
13
+ private log;
14
+ }
15
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/api/client.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAc,MAAM,UAAU,CAAC;AAMrD,qBAAa,cAAc;IACzB,OAAO,CAAC,KAAK,CAAU;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA6B;gBAElD,KAAK,GAAE,OAAe;IAO5B,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAgB3E,aAAa,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAgBzE,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM;YAU3E,KAAK;IAmFnB,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,GAAG;CAKZ"}
@@ -0,0 +1,33 @@
1
+ import type { AlterConnectConfig, OpenOptions } from '../types';
2
+ export declare class AlterConnect {
3
+ private config;
4
+ private eventEmitter;
5
+ private stateManager;
6
+ private apiClient;
7
+ private _modal;
8
+ private _isInitialized;
9
+ private _searchBar;
10
+ private _providerList;
11
+ private _oauthHandler;
12
+ private _baseURL;
13
+ private constructor();
14
+ static create(config?: AlterConnectConfig): AlterConnect;
15
+ open(options: OpenOptions): Promise<void>;
16
+ close(): void;
17
+ destroy(): void;
18
+ updateConfig(config: Partial<AlterConnectConfig>): void;
19
+ getConfig(): Required<AlterConnectConfig>;
20
+ on(event: string, handler: (...args: any[]) => void): () => void;
21
+ off(event: string, handler: (...args: any[]) => void): void;
22
+ isOpen(): boolean;
23
+ getVersion(): string;
24
+ private buildUIContent;
25
+ private handleProviderClick;
26
+ private handleOAuthSuccess;
27
+ private handleOAuthError;
28
+ private handleOAuthCancel;
29
+ private registerEventHandlers;
30
+ private createError;
31
+ private normalizeError;
32
+ }
33
+ //# sourceMappingURL=alter-connect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alter-connect.d.ts","sourceRoot":"","sources":["../../../src/core/alter-connect.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAoC,MAAM,UAAU,CAAC;AAkBlG,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,SAAS,CAAiB;IAClC,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,cAAc,CAAU;IAChC,OAAO,CAAC,UAAU,CAA0B;IAC5C,OAAO,CAAC,aAAa,CAA6B;IAClD,OAAO,CAAC,aAAa,CAA6B;IAClD,OAAO,CAAC,QAAQ,CAAqC;IAKrD,OAAO;IAqCP,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,YAAY;IAyBlD,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IA6H/C,KAAK,IAAI,IAAI;IA0Cb,OAAO,IAAI,IAAI;IA+Cf,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,kBAAkB,CAAC,GAAG,IAAI;IAmBvD,SAAS,IAAI,QAAQ,CAAC,kBAAkB,CAAC;IAOzC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,GAAG,MAAM,IAAI;IAYhE,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,GAAG,IAAI;IAY3D,MAAM,IAAI,OAAO;IAYjB,UAAU,IAAI,MAAM;IAOpB,OAAO,CAAC,cAAc;IAiGtB,OAAO,CAAC,mBAAmB;IA6C3B,OAAO,CAAC,kBAAkB;IAkB1B,OAAO,CAAC,gBAAgB;IAmBxB,OAAO,CAAC,iBAAiB;IAkBzB,OAAO,CAAC,qBAAqB;IAmC7B,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,cAAc;CAiBvB"}
@@ -0,0 +1,19 @@
1
+ import type { AlterConnectConfig } from '../types';
2
+ interface FullConfig {
3
+ customization: {
4
+ colors: {
5
+ primary: string;
6
+ text: string;
7
+ background: string;
8
+ };
9
+ fontFamily: string;
10
+ logoUrl?: string;
11
+ };
12
+ locale: string;
13
+ debug: boolean;
14
+ }
15
+ export declare function validateConfig(config: AlterConnectConfig): void;
16
+ export declare function mergeConfig(config: AlterConnectConfig): FullConfig;
17
+ export declare function debugLog(config: FullConfig, ...args: any[]): void;
18
+ export type { FullConfig };
19
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/core/config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAKnD,UAAU,UAAU;IAClB,aAAa,EAAE;QACb,MAAM,EAAE;YACN,OAAO,EAAE,MAAM,CAAC;YAChB,IAAI,EAAE,MAAM,CAAC;YACb,UAAU,EAAE,MAAM,CAAC;SACpB,CAAC;QACF,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;CAChB;AAqBD,wBAAgB,cAAc,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI,CAkB/D;AAKD,wBAAgB,WAAW,CAAC,MAAM,EAAE,kBAAkB,GAAG,UAAU,CAgBlE;AAKD,wBAAgB,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAIjE;AAKD,YAAY,EAAE,UAAU,EAAE,CAAC"}
@@ -0,0 +1,11 @@
1
+ type EventHandler = (...args: any[]) => void;
2
+ export declare class EventEmitter {
3
+ private events;
4
+ constructor();
5
+ on(event: string, handler: EventHandler): () => void;
6
+ off(event: string, handler: EventHandler): void;
7
+ emit(event: string, ...args: any[]): void;
8
+ removeAllListeners(event?: string): void;
9
+ }
10
+ export {};
11
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../../src/core/events.ts"],"names":[],"mappings":"AAIA,KAAK,YAAY,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;AAK7C,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAiC;;IAU/C,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,MAAM,IAAI;IAcpD,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI;IAU/C,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAgBzC,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;CAOzC"}
@@ -0,0 +1,3 @@
1
+ export { AlterConnect as default } from './core/alter-connect';
2
+ export type { AlterConnectConfig, OpenOptions, Provider, Connection, AlterError, } from './types';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,YAAY,IAAI,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAG/D,YAAY,EACV,kBAAkB,EAClB,WAAW,EACX,QAAQ,EACR,UAAU,EACV,UAAU,GACX,MAAM,SAAS,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { Connection, AlterError } from '../types';
2
+ interface OAuthHandlerOptions {
3
+ onSuccess: (connection: Connection) => void;
4
+ onError: (error: AlterError) => void;
5
+ onCancel: () => void;
6
+ popupWidth?: number;
7
+ popupHeight?: number;
8
+ debug?: boolean;
9
+ }
10
+ export declare class OAuthHandler {
11
+ private popup;
12
+ private pollInterval;
13
+ private messageListener;
14
+ private options;
15
+ constructor(options: OAuthHandlerOptions);
16
+ openPopup(url: string): void;
17
+ close(): void;
18
+ private startPolling;
19
+ private setupMessageListener;
20
+ private log;
21
+ }
22
+ export {};
23
+ //# sourceMappingURL=handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/oauth/handler.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEvD,UAAU,mBAAmB;IAC3B,SAAS,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAC5C,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACrC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAKD,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,eAAe,CAAgD;IACvE,OAAO,CAAC,OAAO,CAAgC;gBAEnC,OAAO,EAAE,mBAAmB;IAcxC,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAoC5B,KAAK,IAAI,IAAI;IAyBb,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,oBAAoB;IAgD5B,OAAO,CAAC,GAAG;CAKZ"}
@@ -0,0 +1,25 @@
1
+ import type { Provider, AlterError } from '../types';
2
+ export interface SDKState {
3
+ isOpen: boolean;
4
+ isLoading: boolean;
5
+ error: AlterError | null;
6
+ sessionToken: string | null;
7
+ providers: Provider[];
8
+ selectedProvider: Provider | null;
9
+ searchQuery: string;
10
+ categoryFilter: string | null;
11
+ }
12
+ type StateListener = (state: SDKState) => void;
13
+ export declare class StateManager {
14
+ private state;
15
+ private listeners;
16
+ constructor();
17
+ getState(): Readonly<SDKState>;
18
+ get<K extends keyof SDKState>(key: K): SDKState[K];
19
+ setState(updates: Partial<SDKState>): void;
20
+ subscribe(listener: StateListener): () => void;
21
+ clearListeners(): void;
22
+ private notifyListeners;
23
+ }
24
+ export {};
25
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../../src/state/manager.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAKrD,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,gBAAgB,EAAE,QAAQ,GAAG,IAAI,CAAC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,KAAK,aAAa,GAAG,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC;AAK/C,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,SAAS,CAAqB;;IAmBtC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC;IAO9B,GAAG,CAAC,CAAC,SAAS,MAAM,QAAQ,EAAE,GAAG,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;IAOlD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI;IAQ1C,SAAS,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,IAAI;IAY9C,cAAc,IAAI,IAAI;IAOtB,OAAO,CAAC,eAAe;CAUxB"}
@@ -0,0 +1,48 @@
1
+ export interface Provider {
2
+ id: string;
3
+ name: string;
4
+ description: string;
5
+ category: string;
6
+ logo_url: string;
7
+ }
8
+ export interface Connection {
9
+ connection_id: string;
10
+ provider: string;
11
+ provider_name: string;
12
+ account_identifier: string;
13
+ timestamp: string;
14
+ operation: 'creation' | 'reauth';
15
+ scopes: string[];
16
+ status: 'active' | 'pending' | 'error';
17
+ metadata?: {
18
+ account_display_name?: string;
19
+ account_email?: string;
20
+ [key: string]: any;
21
+ };
22
+ }
23
+ export interface AlterError {
24
+ code: string;
25
+ message: string;
26
+ details?: Record<string, any>;
27
+ }
28
+ export interface AlterConnectConfig {
29
+ customization?: {
30
+ colors?: {
31
+ primary?: string;
32
+ text?: string;
33
+ background?: string;
34
+ };
35
+ fontFamily?: string;
36
+ };
37
+ locale?: string;
38
+ debug?: boolean;
39
+ }
40
+ export interface OpenOptions {
41
+ token: string;
42
+ baseURL?: string;
43
+ onSuccess: (connection: Connection) => void;
44
+ onExit?: () => void;
45
+ onError?: (error: AlterError) => void;
46
+ onEvent?: (eventName: string, metadata: any) => void;
47
+ }
48
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAKD,MAAM,WAAW,UAAU;IAKzB,aAAa,EAAE,MAAM,CAAC;IAMtB,QAAQ,EAAE,MAAM,CAAC;IAMjB,aAAa,EAAE,MAAM,CAAC;IAMtB,kBAAkB,EAAE,MAAM,CAAC;IAK3B,SAAS,EAAE,MAAM,CAAC;IAKlB,SAAS,EAAE,UAAU,GAAG,QAAQ,CAAC;IAMjC,MAAM,EAAE,MAAM,EAAE,CAAC;IAKjB,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;IAKvC,QAAQ,CAAC,EAAE;QACT,oBAAoB,CAAC,EAAE,MAAM,CAAC;QAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,CAAC;CACH;AAKD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC/B;AAKD,MAAM,WAAW,kBAAkB;IAIjC,aAAa,CAAC,EAAE;QAId,MAAM,CAAC,EAAE;YACP,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,IAAI,CAAC,EAAE,MAAM,CAAC;YACd,UAAU,CAAC,EAAE,MAAM,CAAC;SACrB,CAAC;QAIF,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;IAKF,MAAM,CAAC,EAAE,MAAM,CAAC;IAKhB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAKD,MAAM,WAAW,WAAW;IAK1B,KAAK,EAAE,MAAM,CAAC;IAOd,OAAO,CAAC,EAAE,MAAM,CAAC;IAKjB,SAAS,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAK5C,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAKpB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IAKtC,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,IAAI,CAAC;CACtD"}
@@ -0,0 +1,22 @@
1
+ import type { FullConfig } from '../core/config';
2
+ interface ModalOptions {
3
+ onClose: () => void;
4
+ }
5
+ export declare class Modal {
6
+ private overlay;
7
+ private container;
8
+ private contentEl;
9
+ private closeButton;
10
+ private config;
11
+ private onClose;
12
+ constructor(config: FullConfig);
13
+ open(options: ModalOptions): void;
14
+ setContent(content: HTMLElement): void;
15
+ close(): void;
16
+ destroy(): void;
17
+ private handleClose;
18
+ private handleEscape;
19
+ }
20
+ export declare function injectGlobalStyles(): void;
21
+ export {};
22
+ //# sourceMappingURL=modal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["../../../src/ui/modal.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,UAAU,YAAY;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAKD,qBAAa,KAAK;IAChB,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,OAAO,CAA6B;gBAEhC,MAAM,EAAE,UAAU;IAO9B,IAAI,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IA2GjC,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAUtC,KAAK,IAAI,IAAI;IAuBb,OAAO,IAAI,IAAI;IAOf,OAAO,CAAC,WAAW,CAIjB;IAKF,OAAO,CAAC,YAAY,CAIlB;CACH;AAKD,wBAAgB,kBAAkB,IAAI,IAAI,CA+BzC"}
@@ -0,0 +1,16 @@
1
+ import type { Provider } from '../types';
2
+ import type { FullConfig } from '../core/config';
3
+ type ProviderClickHandler = (provider: Provider) => void;
4
+ export declare class ProviderList {
5
+ private container;
6
+ private config;
7
+ private onProviderClick;
8
+ constructor(config: FullConfig);
9
+ render(providers: Provider[], onProviderClick: ProviderClickHandler): HTMLElement;
10
+ update(providers: Provider[]): void;
11
+ destroy(): void;
12
+ private renderProviders;
13
+ private createProviderButton;
14
+ }
15
+ export {};
16
+ //# sourceMappingURL=provider-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-list.d.ts","sourceRoot":"","sources":["../../../src/ui/provider-list.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,KAAK,oBAAoB,GAAG,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;AAKzD,qBAAa,YAAY;IACvB,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,eAAe,CAAqC;gBAEhD,MAAM,EAAE,UAAU;IAO9B,MAAM,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,eAAe,EAAE,oBAAoB,GAAG,WAAW;IAsBjF,MAAM,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI;IAUnC,OAAO,IAAI,IAAI;IAQf,OAAO,CAAC,eAAe;IA0BvB,OAAO,CAAC,oBAAoB;CAoI7B"}
@@ -0,0 +1,15 @@
1
+ import type { FullConfig } from '../core/config';
2
+ type SearchHandler = (query: string) => void;
3
+ export declare class SearchBar {
4
+ private container;
5
+ private input;
6
+ private config;
7
+ private onSearch;
8
+ constructor(config: FullConfig);
9
+ render(placeholder: string, onSearch: SearchHandler): HTMLElement;
10
+ getValue(): string;
11
+ clear(): void;
12
+ destroy(): void;
13
+ }
14
+ export {};
15
+ //# sourceMappingURL=search-bar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-bar.d.ts","sourceRoot":"","sources":["../../../src/ui/search-bar.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,KAAK,aAAa,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;AAK7C,qBAAa,SAAS;IACpB,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,QAAQ,CAA8B;gBAElC,MAAM,EAAE,UAAU;IAO9B,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,WAAW;IA4EjE,QAAQ,IAAI,MAAM;IAOlB,KAAK,IAAI,IAAI;IAYb,OAAO,IAAI,IAAI;CAKhB"}
package/package.json ADDED
@@ -0,0 +1,74 @@
1
+ {
2
+ "name": "@alter-ai/connect",
3
+ "version": "0.1.0",
4
+ "description": "JavaScript SDK for Alter Connect - Secure OAuth integration UI",
5
+ "main": "dist/alter-connect.cjs.js",
6
+ "module": "dist/alter-connect.esm.js",
7
+ "types": "dist/types/index.d.ts",
8
+ "unpkg": "dist/alter-connect.umd.js",
9
+ "files": [
10
+ "dist",
11
+ "README.md",
12
+ "LICENSE"
13
+ ],
14
+ "scripts": {
15
+ "build": "rollup -c",
16
+ "build:watch": "rollup -c -w",
17
+ "dev": "rollup -c -w",
18
+ "test": "vitest run",
19
+ "test:ci": "vitest run",
20
+ "test:watch": "vitest",
21
+ "test:coverage": "vitest run --coverage",
22
+ "typecheck": "tsc --noEmit",
23
+ "lint": "eslint src",
24
+ "lint:fix": "eslint src --fix",
25
+ "validate": "npm run typecheck && npm run lint && npm run test",
26
+ "prepublishOnly": "npm run validate && npm run build"
27
+ },
28
+ "keywords": [
29
+ "oauth",
30
+ "authentication",
31
+ "alter-vault",
32
+ "connect",
33
+ "integration"
34
+ ],
35
+ "author": "Alter Team <founders@alterai.dev>",
36
+ "license": "MIT",
37
+ "homepage": "https://alterai.dev",
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "git+https://github.com/AlterAIDev/Alter-Vault.git",
41
+ "directory": "apps/alter_connect/sdk"
42
+ },
43
+ "bugs": {
44
+ "url": "https://github.com/AlterAIDev/Alter-Vault/issues"
45
+ },
46
+ "publishConfig": {
47
+ "access": "public",
48
+ "registry": "https://registry.npmjs.org/"
49
+ },
50
+ "engines": {
51
+ "node": ">=16.0.0"
52
+ },
53
+ "devDependencies": {
54
+ "@rollup/plugin-commonjs": "^25.0.7",
55
+ "@rollup/plugin-node-resolve": "^15.2.3",
56
+ "@rollup/plugin-terser": "^0.4.4",
57
+ "@rollup/plugin-typescript": "^11.1.5",
58
+ "@types/jest": "^29.5.11",
59
+ "@typescript-eslint/eslint-plugin": "^8.53.0",
60
+ "@typescript-eslint/parser": "^8.53.0",
61
+ "@vitest/ui": "^1.0.4",
62
+ "eslint": "^9.0.0",
63
+ "happy-dom": "^12.10.3",
64
+ "jest": "^29.7.0",
65
+ "jest-environment-jsdom": "^29.7.0",
66
+ "rollup": "^4.9.4",
67
+ "ts-jest": "^29.1.1",
68
+ "tslib": "^2.6.2",
69
+ "typescript": "^5.3.3",
70
+ "typescript-eslint": "^8.53.0",
71
+ "vitest": "^1.0.4"
72
+ },
73
+ "dependencies": {}
74
+ }