@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
Markdown
# 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.