UNPKG

@darksnow-ui/commander

Version:

Command pattern implementation with React hooks for building command palettes and keyboard-driven UIs

338 lines (269 loc) 9.4 kB
# Commander Algorithm - Arquitetura e Funcionamento ## 📋 Visão Geral O **Commander** é o motor central do sistema - uma classe que implementa o padrão Command com funcionalidades enterprise. É responsável por gerenciar, executar e organizar comandos de forma eficiente e escalável. ## 🏗️ Arquitetura Core ### Estruturas de Dados Principais ```typescript class Commander { private commands = new Map<CommandKey, Command>() // O(1) lookup por chave private executionHistory: ExecutionContext[] = [] // Buffer circular private recentCommands = new Map<CommandKey, Command>() // LRU cache private listeners = new Map<string, EventListener[]>() // Pub/Sub system public maxHistorySize = 100 // Limite do histórico public maxRecentSize = 10 // Limite de comandos recentes } ``` **Decisões de Design:** - **Map para comandos**: Lookup O(1) vs Array O(n) - **Buffer circular para histórico**: Memória limitada, performance consistente - **LRU para recentes**: Acesso rápido aos comandos mais usados - **Map para eventos**: Múltiplos listeners por evento ## ⚙️ Algoritmos de Execução ### 1. Command Execution Pipeline ``` invoke(key, input, source) → ├── 1. Command Lookup (O(1)) ├── 2. Availability Check (O(1) ou Promise) ├── 3. Event: "command:executing" ├── 4. Handler Execution (com timeout) ├── 5. History Tracking ├── 6. Recent Commands Update └── 7. Event: "command:completed" | "command:failed" ``` **Características:** - **Timeout Protection**: Execução limitada por tempo - **Error Handling**: Try/catch com wrapping em CommandExecutionError - **Event Tracking**: Full lifecycle observability - **Source Tracking**: "api", "palette", "shortcut" ### 2. Search Algorithm ```typescript async search(query: string, options?: SearchOptions): Promise<SearchResult[]> ``` **Algoritmo de Scoring Hierárquico:** ``` Para cada comando: ├── 1. Filtros (categoria, owner, tags) ├── 2. Availability Check (se includeUnavailable = false) ├── 3. Score Calculation: │ ├── Label exact match: 100 pontos │ ├── Label partial match: 80 pontos │ ├── Description match: 60 pontos │ ├── Tags match: 40 pontos │ ├── SearchKeywords match: 50 pontos │ └── Fuzzy matching: 1-30 pontos ├── 4. Sort by score (desc) └── 5. Limit results ``` **Complexidade:** O(n × m) onde n = comandos, m = termos de busca ### 3. History Management **Buffer Circular Implementation:** ```typescript private addToHistory(context: ExecutionContext) { this.executionHistory.unshift(context) if (this.executionHistory.length > this.maxHistorySize) { this.executionHistory = this.executionHistory.slice(0, this.maxHistorySize) } } ``` **Recent Commands (LRU):** ```typescript private updateRecentCommands(command: Command) { // Remove se já existe (move para frente) this.recentCommands.delete(command.key) // Adiciona no início this.recentCommands.set(command.key, command) // Mantém tamanho máximo if (this.recentCommands.size > this.maxRecentSize) { const firstKey = this.recentCommands.keys().next().value this.recentCommands.delete(firstKey) } } ``` ## 🎯 Sistema de Eventos (Pub/Sub) ### Event Lifecycle ``` Command Execution: ├── command:executing → { command, input, source, startTime } ├── command:completed → { command, input, result, duration } └── command:failed → { command, input, error, duration } Command Management: ├── command:added → { command } └── command:removed → { command } ``` ### Event System Implementation ```typescript listen(event: string, callback: Function, options?: { once?: boolean }) { const listener = { callback, once: options?.once || false } if (!this.listeners.has(event)) { this.listeners.set(event, []) } this.listeners.get(event)!.push(listener) return listener // Para remoção posterior } private emit(event: string, ...args: any[]) { const listeners = this.listeners.get(event) || [] listeners.forEach(listener => { try { listener.callback(...args) } catch (error) { console.error(`Event listener error for "${event}":`, error) } }) // Remove listeners "once" this.listeners.set(event, listeners.filter(l => !l.once)) } ``` ## 🔍 Command Lookup e Filtering ### 1. Basic Lookup ```typescript has(key: CommandKey): boolean { return this.commands.has(key) // O(1) } getCommand(key: CommandKey): Command | undefined { return this.commands.get(key) // O(1) } ``` ### 2. Filtered Queries ```typescript getAvailableCommands(options?: FilterOptions): Promise<Command[]> { return Promise.all( Array.from(this.commands.values()) .filter(cmd => matchesFilters(cmd, options)) .map(async cmd => ({ command: cmd, available: await this.isCommandAvailable(cmd) })) ).then(results => results .filter(r => r.available) .map(r => r.command) ) } ``` ### 3. Category Organization ```typescript getCommandsByCategory(): Map<CommandCategory, Command[]> { const categories = new Map<CommandCategory, Command[]>() for (const command of this.commands.values()) { const category = command.category || 'custom' if (!categories.has(category)) { categories.set(category, []) } categories.get(category)!.push(command) } return categories } ``` ## ⚡ Performance Optimizations ### 1. Lazy Evaluation - **Availability checks**: Só executados quando necessário - **Event emission**: Só dispara se há listeners - **History**: Só mantém registros necessários ### 2. Memory Management - **History circular**: Evita vazamentos de memória - **Recent commands LRU**: Tamanho limitado - **Event cleanup**: Remove listeners "once" automaticamente ### 3. Search Optimizations - **Early filtering**: Aplica filtros antes do scoring - **Limit results**: Para busca prematura - **Cache availability**: Para comandos que não mudam ## 🛡️ Error Handling ### Error Types ```typescript // Comando não encontrado class CommandNotFoundError extends Error // Comando indisponível (when() = false) class CommandUnavailableError extends Error // Timeout na execução class CommandTimeoutError extends Error // Erro durante execução class CommandExecutionError extends Error { constructor(message: string, public cause?: Error) } ``` ### Execution Safety ```typescript async attempt<T>(key: CommandKey, input?: any): Promise<ExecutionResult<T>> { try { const result = await this.invoke<T>(key, input) return { success: true, result, error: null } } catch (error) { return { success: false, result: null, error: error instanceof Error ? error : new Error(String(error)) } } } ``` ## 📊 Statistics e Monitoring ### Stats Collection ```typescript getStats() { return { totalCommands: this.commands.size, categories: new Set(Array.from(this.commands.values()).map(c => c.category || 'custom')).size, executionHistory: this.executionHistory.length, recentCommands: this.recentCommands.size, listeners: Array.from(this.listeners.values()).reduce((sum, arr) => sum + arr.length, 0) } } ``` ## 🎛️ Command Invoker Pattern ### Invoker Creation ```typescript createInvoker<TInput, TOutput>(key: CommandKey): CommandInvoker<TInput, TOutput> { return { exists: () => this.has(key), isAvailable: () => this.isCommandAvailable(this.getCommand(key)!), getCommand: () => this.getCommand(key), invoke: (input?: TInput) => this.invoke<TOutput>(key, input), attempt: (input?: TInput) => this.attempt<TOutput>(key, input) } } ``` ## 🏆 Características Enterprise ### 1. Scalability - **Suporta 500+ comandos** sem degradação - **O(1) lookups** para operações críticas - **Memory bounded** com histórico circular ### 2. Observability - **Comprehensive events** para monitoring - **Execution tracking** com timing - **Error reporting** estruturado ### 3. Reliability - **Timeout protection** contra comandos travados - **Error isolation** entre comandos - **Graceful degradation** com availability checks ### 4. Maintainability - **Clear separation** entre storage e logic - **Consistent API** para todas as operações - **Extensive testing** coverage ## 🚀 Algoritmo de Inicialização ```typescript constructor() { // 1. Initialize data structures this.commands = new Map() this.executionHistory = [] this.recentCommands = new Map() this.listeners = new Map() // 2. Set default configuration this.maxHistorySize = 100 this.maxRecentSize = 10 // 3. Ready to accept commands } ``` ## 📈 Complexity Analysis | Operation | Time Complexity | Space Complexity | |-----------|----------------|------------------| | `add(command)` | O(1) | O(1) | | `remove(key)` | O(1) | O(1) | | `has(key)` | O(1) | O(1) | | `invoke(key)` | O(1) + handler | O(1) | | `search(query)` | O(n × m) | O(n) | | `getAvailableCommands()` | O(n) | O(n) | | `getCommandsByCategory()` | O(n) | O(n) | **Onde:** - n = número de comandos - m = número de termos na busca O Commander foi projetado para ser **eficiente, confiável e escalável**, implementando as melhores práticas de algoritmos e estruturas de dados para sistemas enterprise.