UNPKG

@darksnow-ui/commander

Version:

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

323 lines (254 loc) 9.59 kB
# Análise dos Algoritmos do Commander ## Visão Geral O @darksnow-ui/commander implementa um sistema de comandos enterprise-grade para React, inspirado em editores modernos como VS Code. Esta análise detalha os algoritmos centrais, decisões de design e a cobertura de testes. ## Arquitetura de Algoritmos ### 1. **Command Builder Pattern** (`builder.ts`) #### Propósito Implementa o padrão Builder para criar comandos de forma fluente e type-safe. #### Algoritmo Principal ```typescript class CommandBuilder<TInput, TOutput> { private command: Partial<Command<TInput, TOutput>> = {}; // Métodos fluentes que retornam 'this' para chaining key(key: CommandKey): this { ... } label(label: string): this { ... } handle(handler: Function): this { ... } // Validação e construção final build(): Command<TInput, TOutput> { // Valida campos obrigatórios // Retorna comando completo e type-safe } } ``` #### Características Notáveis - **Fluent Interface**: Todos os métodos retornam `this` para permitir chaining - **Type Safety**: Generics `<TInput, TOutput>` garantem tipagem end-to-end - **Validação Eager**: Validações ocorrem nos setters individuais (ex: timeout > 0) - **Templates Pré-definidos**: Métodos estáticos para categorias comuns (system, file, debug) ### 2. **Core Commander Engine** (`commander.ts`) #### Estrutura de Dados ```typescript class Commander { private _commands: Map<CommandKey, Command> = new Map(); private listeners: Map<string, EventListener[]> = new Map(); private executionHistory: CommandExecutionContext[] = []; private recentCommands: CommandKey[] = []; } ``` #### Algoritmos Principais ##### **2.1 Sistema de Busca com Scoring** O algoritmo de busca implementa um sistema de pontuação multi-nível: ```typescript function calculateSearchScore(command: Command, queryTerms: string[]): number { let score = 0; queryTerms.forEach(term => { // Pontuação hierárquica if (label.toLowerCase() === term) score += 100; // Match exato else if (label.includes(term)) score += 50; // Match parcial if (description.includes(term)) score += 25; // Na descrição if (tags.includes(term)) score += 15; // Nas tags if (keywords.includes(term)) score += 10; // Nas palavras-chave if (searchableText.includes(term)) score += 5; // Fuzzy match }); return score; } ``` **Complexidade**: O(n × m) onde n = comandos, m = termos de busca ##### **2.2 Sistema de Eventos** Implementa pub/sub pattern com suporte a listeners únicos: ```typescript listen(event: string, callback: Function, options?: { once?: boolean }) { const listener = { id: generateId(), event, callback, once: options?.once }; // Adiciona ao Map de listeners // Retorna handle para remoção } emit(event: string, ...args: any[]) { // Executa todos os listeners // Remove one-time listeners após execução } ``` ##### **2.3 Execução com Timeout** Usa Promise.race para implementar timeouts: ```typescript function withTimeout<T>(promise: Promise<T>, timeoutMs: number): Promise<T> { return Promise.race([ promise, new Promise<never>((_, reject) => { setTimeout(() => reject(new Error('timeout')), timeoutMs); }) ]); } ``` ##### **2.4 Rastreamento de Histórico** Implementa buffer circular para histórico: ```typescript trackExecution(context: CommandExecutionContext) { this.executionHistory.push(context); // Mantém tamanho máximo if (this.executionHistory.length > this.maxHistorySize) { this.executionHistory.splice(0, this.executionHistory.length - this.maxHistorySize ); } } ``` ### 3. **Utilitários e Estruturas de Dados** (`utils.ts`) #### **3.1 Priority Queue** Implementação de fila de prioridade com inserção ordenada: ```typescript class PriorityQueue<T> { private items: Array<{ item: T; priority: number }> = []; enqueue(item: T, priority: number): void { // Inserção ordenada O(n) for (let i = 0; i < this.items.length; i++) { if (priority > this.items[i].priority) { this.items.splice(i, 0, { item, priority }); return; } } this.items.push({ item, priority }); } dequeue(): T | undefined { return this.items.shift()?.item; // O(n) devido ao shift } } ``` **Nota**: Implementação simples adequada para listas pequenas. Para grandes volumes, heap binário seria mais eficiente. #### **3.2 Deep Clone** Implementação recursiva com suporte a tipos especiais: ```typescript function deepClone<T>(obj: T): T { if (obj === null || typeof obj !== 'object') return obj; if (obj instanceof Date) return new Date(obj.getTime()) as T; if (obj instanceof Array) return obj.map(deepClone) as T; const cloned = {} as T; for (const key in obj) { if (obj.hasOwnProperty(key)) { cloned[key] = deepClone(obj[key]); } } return cloned; } ``` #### **3.3 Debounce** Implementação clássica com suporte a execução imediata: ```typescript function debounce<T extends Function>(func: T, wait: number, immediate = false) { let timeout: NodeJS.Timeout | undefined; return function(...args: Parameters<T>) { const callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(() => { timeout = undefined; if (!immediate) func(...args); }, wait); if (callNow) func(...args); }; } ``` ### 4. **Sistema de Tipos** (`types.ts`) #### Decisões de Design ##### **Branded Types** ```typescript export type CommandKey = string & { __brand: 'CommandKey' }; ``` Previne uso acidental de strings não validadas como chaves. ##### **Categorias Fixas** ```typescript export type CommandCategory = 'system' | 'file' | 'edit' | 'view' | 'debug' | 'tools' | 'custom'; ``` Union type finito garante consistência e autocomplete. ##### **Handler com Contexto** ```typescript handle: (this: Commander, input?: TInput) => Promise<TOutput>; ``` Handler recebe `Commander` como `this`, permitindo acesso ao sistema. ## Cobertura de Testes ### **utils.test.ts** (50 testes) #### Testes de Search Scoring - Verifica pontuação hierárquica correta - Testa acumulação de pontos para múltiplas categorias - Valida case-insensitive search - Confirma que termos não encontrados retornam score 0 #### Testes da PriorityQueue - Inserção e remoção por prioridade - Manutenção de FIFO para mesma prioridade - Operações de peek sem remoção - Remoção por predicado - Tratamento de prioridades negativas e default (0) #### Testes de Utilitários - `deepClone`: Objetos, arrays, Date, primitivos, herança - `debounce`: Throttling de chamadas, argumentos mais recentes - `withTimeout`: Resolução antes/depois do timeout, preservação de erros - `unique`, `removeItem`: Operações de array ### **builder.test.ts** (23 testes) #### Construção Básica - Comando mínimo (key, label, handle) - Comando com todas as propriedades - Validação de campos obrigatórios - Method chaining #### Type Safety - Inferência correta de tipos Input/Output - Propagação de tipos através do builder #### Templates - Verificação de defaults por categoria - Override de propriedades de template #### Métodos Especiais - `clone()`: Cópia independente do builder - `reset()`: Limpeza completa do estado - `getState()`: Snapshot do estado atual ### **commander.test.ts** (40 testes) #### Gerenciamento de Comandos - CRUD operations (add, remove, get, has) - Remoção por owner/category em batch - Substituição de comandos existentes #### Sistema de Execução - Invocação com input/output tipados - Tratamento de erros (NotFound, Unavailable, Timeout, Execution) - Condições síncronas e assíncronas (`when`) - Rastreamento de source (palette, shortcut, api) #### Sistema de Busca - Query por texto com scoring - Filtros por categoria, owner, tags - Limite de resultados - Inclusão/exclusão de comandos indisponíveis #### Sistema de Eventos - Eventos de ciclo de vida (executing, completed, failed) - Eventos de mudança (added, removed) - Listeners únicos (once) - Remoção de listeners #### Histórico e Analytics - Rastreamento de execuções - Buffer circular com limite configurável - Lista de comandos recentes - Limpeza de histórico #### CommandHandler/Invoker - Criação de invokers tipados - Verificação de disponibilidade - Execução segura com attempt() - Acesso ao comando via invoker ## Insights e Padrões Identificados ### 1. **Separation of Concerns** - Builder para construção - Commander para execução e gerenciamento - Utils para algoritmos genéricos - Types para contratos ### 2. **Type Safety First** - Uso extensivo de generics - Branded types para valores especiais - Inferência automática onde possível ### 3. **Performance Considerations** - Maps para O(1) lookups - Lazy evaluation de condições - Debounce para operações frequentes - Limites de memória configuráveis ### 4. **Error Handling** - Hierarquia de erros específica - Wrapping consistente de erros - Preservação de stack traces ### 5. **Extensibilidade** - Sistema de eventos para plugins - Templates para casos comuns - Handlers com acesso ao contexto ## Conclusão O Commander implementa um sistema robusto e bem arquitetado para gerenciamento de comandos em React. Os algoritmos são eficientes para o caso de uso típico (centenas de comandos), com complexidade adequada e boa separação de responsabilidades. A cobertura de testes é excelente, validando tanto casos comuns quanto edge cases.