# Commander Architecture

> Documentação técnica da arquitetura do `@darksnow-ui/commander`

## Visão Geral

O **Commander** é um sistema de gerenciamento de comandos enterprise-grade para aplicações React. Implementa o padrão Command com funcionalidades avançadas como validação de input, sistema de eventos, busca inteligente e histórico de execução.

```
┌─────────────────────────────────────────────────────────────────────────────┐
│                           @darksnow-ui/commander                            │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  ┌─────────────┐    ┌─────────────┐    ┌─────────────┐    ┌─────────────┐  │
│  │   React     │    │  Commander  │    │   Builder   │    │   Errors    │  │
│  │   Hooks     │───▶│    Core     │◀───│   Pattern   │    │   System    │  │
│  └─────────────┘    └─────────────┘    └─────────────┘    └─────────────┘  │
│        │                  │                  │                  │          │
│        │                  │                  │                  │          │
│        ▼                  ▼                  ▼                  ▼          │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │                          Types & Interfaces                         │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
```

---

## Estrutura de Arquivos

```
src/
├── commander.ts          # Classe principal Commander
├── builder.ts            # CommandBuilder e templates
├── errors.ts             # Classes de erro customizadas
├── types.ts              # Tipos e interfaces TypeScript
├── utils.ts              # Funções utilitárias
├── index.ts              # Exports públicos
│
├── hooks/
│   ├── index.ts          # Re-exports dos hooks
│   ├── context.tsx       # CommanderProvider e useCommander
│   ├── useCommand.ts     # Hook principal para executar comandos
│   ├── useCustomCommand.ts # Hook para registrar comandos temporários
│   └── useInvoker.ts     # Hook simplificado para invocação
│
└── __tests__/
    ├── commander.test.ts
    ├── builder.test.ts
    ├── validation.test.ts
    ├── utils.test.ts
    └── ...hooks tests
```

---

## Core: Commander Class

### Estruturas de Dados

```typescript
class Commander {
  // Armazenamento principal - Map para O(1) lookup
  protected _commands: Map<CommandKey, Command> = new Map();

  // Sistema de eventos Pub/Sub
  protected listeners: Map<string, EventListener[]> = new Map();

  // Histórico de execuções (buffer circular)
  protected executionHistory: CommandExecutionContext[] = [];

  // Comandos recentes (LRU cache)
  protected recentCommands: CommandKey[] = [];

  // Configurações
  public maxHistorySize = 100;
  public maxRecentSize = 10;
}
```

### Decisões de Design

| Estrutura | Escolha | Justificativa |
|-----------|---------|---------------|
| Commands | `Map<CommandKey, Command>` | O(1) lookup por chave |
| Listeners | `Map<string, EventListener[]>` | Múltiplos listeners por evento |
| History | `Array` (circular) | Memória limitada, FIFO natural |
| Recent | `Array` (LRU) | Ordem de acesso importa |

---

## Pipeline de Execução

### Fluxo do `invoke()`

```
invoke(key, input, source)
│
├── 1. COMMAND LOOKUP ─────────────────────────────────── O(1)
│   └── Map.get(key)
│   └── Throw CommandNotFoundError if missing
│
├── 2. AVAILABILITY CHECK ─────────────────────────────── O(1) ou async
│   └── command.when() → boolean
│   └── Throw CommandUnavailableError if false
│
├── 3. INPUT VALIDATION ───────────────────────────────── O(1) ou async
│   └── command.inputValidator(input) → true | errors[]
│   └── Throw InputValidationError if errors
│   └── Emit "command:validation-error" event
│
├── 4. BUILD CONTEXT ──────────────────────────────────── O(1)
│   └── { command, input, startTime, source }
│
├── 5. EMIT "command:executing" ───────────────────────── O(n listeners)
│
├── 6. EXECUTE WITH TIMEOUT ───────────────────────────── O(handler)
│   └── Promise.race([handler, timeout])
│   └── Throw CommandTimeoutError if exceeded
│
├── 7. TRACK EXECUTION ────────────────────────────────── O(1)
│   └── Add to history (circular buffer)
│   └── Update recent commands (LRU)
│
├── 8. EMIT "command:completed" ───────────────────────── O(n listeners)
│
└── 9. RETURN RESULT ──────────────────────────────────── O(1)
```

### Diagrama de Sequência

```
┌──────────┐     ┌───────────┐     ┌─────────┐     ┌─────────┐
│  Client  │     │ Commander │     │ Command │     │ Handler │
└────┬─────┘     └─────┬─────┘     └────┬────┘     └────┬────┘
     │                 │                │               │
     │ invoke(key,in)  │                │               │
     │────────────────▶│                │               │
     │                 │                │               │
     │                 │ get(key)       │               │
     │                 │───────────────▶│               │
     │                 │                │               │
     │                 │ when()         │               │
     │                 │───────────────▶│               │
     │                 │◀───────────────│               │
     │                 │                │               │
     │                 │ inputValidator()               │
     │                 │───────────────▶│               │
     │                 │◀───────────────│               │
     │                 │                │               │
     │                 │ emit("executing")              │
     │                 │─ ─ ─ ─ ─ ─ ─ ─▶│               │
     │                 │                │               │
     │                 │ handle(input)  │               │
     │                 │───────────────────────────────▶│
     │                 │                │               │
     │                 │◀───────────────────────────────│
     │                 │                │    result     │
     │                 │                │               │
     │                 │ trackExecution()               │
     │                 │─ ─ ─ ─ ─ ─ ─ ─▶│               │
     │                 │                │               │
     │                 │ emit("completed")              │
     │                 │─ ─ ─ ─ ─ ─ ─ ─▶│               │
     │                 │                │               │
     │◀────────────────│                │               │
     │     result      │                │               │
     │                 │                │               │
```

---

## Sistema de Tipos

### Hierarquia de Tipos

```typescript
// Tipos base (branded types para type safety)
type CommandKey = string & { __brand: "CommandKey" };
type CommandCategory = "system" | "file" | "edit" | "view" | "debug" | "tools" | "custom";

// Interface principal do comando
interface Command<TInput = any, TOutput = any> {
  // Identificação (required)
  key: CommandKey;
  label: string;
  handle: (input?: TInput) => Promise<TOutput>;

  // Metadados (optional)
  description?: string;
  category?: CommandCategory;
  owner?: string;
  tags?: string[];
  icon?: string;
  shortcut?: string;
  searchKeywords?: string[];
  priority?: number;
  timeout?: number;

  // Comportamento (optional)
  when?: () => boolean | Promise<boolean>;
  inputValidator?: InputValidator<TInput>;
}

// Validação de input
interface ValidationErrorDetail {
  path: string;      // "email", "user.name", "items[0].id"
  message: string;   // "Email is required"
  code?: string;     // "required", "type", "format"
  expected?: unknown;
  received?: unknown;
}

type ValidationResult = true | ValidationErrorDetail[];
type InputValidator<T> = (input: T | undefined) => ValidationResult | Promise<ValidationResult>;
```

### Diagrama de Tipos

```
                    ┌─────────────────┐
                    │    Command      │
                    │  <TInput,TOut>  │
                    └────────┬────────┘
                             │
         ┌───────────────────┼───────────────────┐
         │                   │                   │
         ▼                   ▼                   ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│   CommandKey    │ │ InputValidator  │ │  CommandCategory│
│   (branded)     │ │   <TInput>      │ │    (union)      │
└─────────────────┘ └────────┬────────┘ └─────────────────┘
                             │
                             ▼
                    ┌─────────────────┐
                    │ValidationResult │
                    │ true | errors[] │
                    └────────┬────────┘
                             │
                             ▼
                    ┌─────────────────┐
                    │ValidationError  │
                    │    Detail       │
                    └─────────────────┘
```

---

## Sistema de Validação

### Fluxo de Validação

```
Input → inputValidator() → ValidationResult
                               │
                    ┌──────────┴──────────┐
                    │                     │
                    ▼                     ▼
                  true              ValidationErrorDetail[]
                    │                     │
                    ▼                     ▼
              Continue to           Throw InputValidationError
               handler                    │
                                          ▼
                                   Emit "command:validation-error"
```

### InputValidationError

```typescript
class InputValidationError extends CommandError {
  errors: ValidationErrorDetail[];
  input?: unknown;

  // Helper methods
  getFieldErrors(path: string): ValidationErrorDetail[];
  getRequiredErrors(): ValidationErrorDetail[];
  getMissingFields(): string[];
  hasFieldError(path: string): boolean;
  toJSON(): object;
}
```

### Integração com Bibliotecas

```typescript
// Zod
inputValidator: (input) => {
  const result = schema.safeParse(input);
  if (result.success) return true;
  return result.error.issues.map(i => ({
    path: i.path.join('.'),
    message: i.message,
    code: i.code
  }));
}

// Yup
inputValidator: async (input) => {
  try {
    await schema.validate(input, { abortEarly: false });
    return true;
  } catch (err) {
    return err.inner.map(e => ({
      path: e.path,
      message: e.message,
      code: e.type
    }));
  }
}

// AJV (JSON Schema)
inputValidator: (input) => {
  const valid = ajv.validate(schema, input);
  if (valid) return true;
  return ajv.errors.map(e => ({
    path: e.instancePath.slice(1).replace(/\//g, '.'),
    message: e.message,
    code: e.keyword
  }));
}
```

---

## Sistema de Eventos

### Eventos Disponíveis

| Evento | Payload | Quando |
|--------|---------|--------|
| `command:added` | `Command` | Comando registrado |
| `command:removed` | `Command` | Comando removido |
| `command:executing` | `CommandExecutionContext` | Antes da execução |
| `command:completed` | `CommandExecutionContext, result` | Execução bem-sucedida |
| `command:failed` | `CommandExecutionContext, error` | Execução falhou |
| `command:error` | `CommandKey, error` | Erro geral (not found, unavailable) |
| `command:validation-error` | `CommandKey, InputValidationError` | Validação falhou |
| `history:cleared` | - | Histórico limpo |

### Arquitetura Pub/Sub

```
┌─────────────────────────────────────────────────────────────┐
│                    Event System                              │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│   listeners: Map<string, EventListener[]>                   │
│                                                              │
│   ┌─────────────────┐  ┌─────────────────┐                  │
│   │ "command:added" │  │"command:executing"│                │
│   ├─────────────────┤  ├─────────────────┤                  │
│   │ [listener1]     │  │ [listener1]     │                  │
│   │ [listener2]     │  │ [listener2]     │                  │
│   │ [listener3]     │  │ [listener3]     │                  │
│   └─────────────────┘  └─────────────────┘                  │
│                                                              │
│   emit(event, ...args)                                      │
│   └── Promise.allSettled(listeners.map(l => l.callback()))  │
│                                                              │
└─────────────────────────────────────────────────────────────┘
```

### Opções de Listener

```typescript
// Listener permanente
const listener = commander.listen("command:completed", (ctx, result) => {
  analytics.track("command_executed", { key: ctx.command.key });
});

// Listener único (auto-remove após primeira execução)
commander.listen("command:added", handler, { once: true });

// Remover listener
commander.removeListener(listener);
```

---

## Sistema de Busca

### Algoritmo de Scoring

```
Para cada comando que passa nos filtros:
│
├── Label exact match ──────────────── +100 pontos
├── Label starts with ─────────────── +80 pontos
├── Label contains ────────────────── +60 pontos
├── Description match ─────────────── +40 pontos
├── Tags match ────────────────────── +30 pontos
├── SearchKeywords match ──────────── +50 pontos
├── Fuzzy match (Levenshtein) ─────── +1-30 pontos
│
└── Sort by: score (desc) → priority (desc)
```

### Complexidade

| Operação | Complexidade | Notas |
|----------|--------------|-------|
| `search(query)` | O(n × m) | n = comandos, m = termos |
| `getAllAvailable()` | O(n) | Com availability check |
| `getCommandsByCategory()` | O(n) | Agrupa por categoria |

---

## React Hooks

### Hierarquia de Hooks

```
                     ┌─────────────────────┐
                     │ CommanderProvider   │
                     │ (Context Provider)  │
                     └──────────┬──────────┘
                                │
                     ┌──────────┴──────────┐
                     │   useCommander()    │
                     │  (Context Consumer) │
                     └──────────┬──────────┘
                                │
         ┌──────────────────────┼──────────────────────┐
         │                      │                      │
         ▼                      ▼                      ▼
┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐
│   useCommand    │  │ useCustomCommand│  │   useInvoker    │
│   (Execution)   │  │  (Registration) │  │  (Simplified)   │
└─────────────────┘  └─────────────────┘  └─────────────────┘
```

### useCommand - API Completa

```typescript
interface CommandInvoker<TInput, TOutput> {
  // Estado
  exists: boolean;
  isAvailable: boolean;
  isLoading: boolean;
  lastResult: TOutput | null;
  lastError: Error | null;
  lastInput: TInput | null;
  lastExecution: Date | null;
  executionCount: number;
  command: Command | null;

  // Métodos de execução
  invoke(input?, options?): Promise<TOutput>;
  attempt(input?, options?): Promise<ExecutionResult<TOutput>>;
  execute(input?, callbacks?): Promise<TOutput | null>;

  // Verificações
  canInvoke(input?): Promise<boolean>;
  validateInput(input?): boolean | string;

  // Utilitários
  reset(): void;
  clearError(): void;
  refresh(): void;
}
```

### Opções do useCommand

```typescript
interface UseCommandOptions<TInput, TOutput> {
  // Execução
  source?: "palette" | "shortcut" | "api";
  throwOnError?: boolean;
  timeout?: number;

  // Retry & Rate Limiting
  retry?: number;
  retryDelay?: number | ((attempt: number) => number);
  debounce?: number;
  throttle?: number;

  // Input handling
  defaultInput?: Partial<TInput>;
  validateInput?: (input?: TInput) => boolean | string;
  transformInput?: (input?: TInput) => TInput;

  // Output handling
  transformOutput?: (output: TOutput) => TOutput;

  // Callbacks
  onSuccess?: (result: TOutput, input?: TInput) => void;
  onError?: (error: Error, input?: TInput) => void;
  onFinally?: (input?: TInput) => void;

  // Estado
  resetOnKeyChange?: boolean;
}
```

---

## Builder Pattern

### CommandBuilder API

```typescript
CommandBuilder.create<TInput, TOutput>("command:key")
  .label("Command Label")              // Required
  .description("Description")          // Optional
  .category("tools")                   // Optional
  .owner("my-module")                  // Optional
  .tags("tag1", "tag2")                // Optional
  .icon("icon-name")                   // Optional
  .shortcut("ctrl+shift+p")            // Optional
  .searchKeywords("keyword1", "kw2")   // Optional
  .priority(10)                        // Optional
  .timeout(5000)                       // Optional
  .when(() => isFeatureEnabled)        // Optional
  .inputValidator(validator)           // Optional
  .handle(async (input) => result)     // Required
  .build();
```

### Templates

```typescript
// Comandos pré-configurados por categoria
CommandTemplate.system()  // category: "system", owner: "system", priority: 10
CommandTemplate.file()    // category: "file", tags: ["file"], priority: 5
CommandTemplate.debug()   // category: "debug", when: () => isDev, priority: 15
CommandTemplate.view()    // category: "view", tags: ["view", "ui"], priority: 3
CommandTemplate.tools()   // category: "tools", tags: ["tools", "utility"], priority: 8
CommandTemplate.custom()  // category: "custom", owner: "temporary", priority: 1
```

---

## Hierarquia de Erros

```
Error
└── CommandError
    ├── CommandNotFoundError      # Comando não existe
    ├── CommandUnavailableError   # when() retornou false
    ├── CommandTimeoutError       # Timeout excedido
    ├── CommandExecutionError     # Erro durante handle()
    └── InputValidationError      # Validação de input falhou
```

### Factory de Erros

```typescript
createCommandError(type, command, details?)

// Tipos:
// "not-found"   → CommandNotFoundError
// "unavailable" → CommandUnavailableError
// "timeout"     → CommandTimeoutError(command, details.timeout)
// "execution"   → CommandExecutionError(command, details.error)
// "validation"  → InputValidationError(command, details.errors, details.input)
```

### Type Guards

```typescript
isInputValidationError(error)  // error is InputValidationError
isCommandError(error)          // error is CommandError
```

---

## Performance

### Análise de Complexidade

| Operação | Time | Space | Notas |
|----------|------|-------|-------|
| `add(command)` | O(1) | O(1) | Map.set |
| `remove(key)` | O(1) | O(1) | Map.delete |
| `has(key)` | O(1) | O(1) | Map.has |
| `getCommand(key)` | O(1) | O(1) | Map.get |
| `invoke(key)` | O(1) + handler | O(1) | Lookup + execute |
| `search(query)` | O(n × m) | O(n) | n=commands, m=terms |
| `getAvailableCommands()` | O(n) | O(n) | Async availability |
| `getCommandsByCategory()` | O(n) | O(n) | Grouping |

### Otimizações

1. **Lazy Evaluation**
   - Availability checks só quando necessário
   - Event emission só se há listeners
   - History tracking com buffer limitado

2. **Memory Management**
   - History circular (max 100 entries)
   - Recent commands LRU (max 10 entries)
   - Listeners cleanup automático para `once`

3. **Search Optimizations**
   - Early filtering antes do scoring
   - Limit results para parar busca
   - Normalização de termos com cache

---

## Boas Práticas

### Nomenclatura de Commands

```typescript
// Padrão: <domain>:<action> ou <domain>:<entity>:<action>
"file:save"
"file:open"
"user:create"
"user:profile:update"
"admin:users:delete"
```

### Organização por Owner

```typescript
// Componente registra seus comandos
useCustomCommand({
  key: "editor:format",
  label: "Format Document",
  owner: "editor-component",  // ← identificação
  handle: async () => formatDocument()
});

// Cleanup automático quando componente desmonta
// ou manual:
commander.removeByOwner("editor-component");
```

### Validação de Input

```typescript
// Sempre valide inputs críticos
commander.add({
  key: "payment:process",
  label: "Process Payment",
  inputValidator: (input) => {
    const errors = [];
    if (!input?.amount || input.amount <= 0) {
      errors.push({ path: "amount", message: "Invalid amount", code: "invalid" });
    }
    if (!input?.cardToken) {
      errors.push({ path: "cardToken", message: "Card required", code: "required" });
    }
    return errors.length ? errors : true;
  },
  handle: async (input) => processPayment(input)
});
```

### Error Handling

```typescript
// Usando attempt() para não lançar exceção
const result = await commander.attempt("risky:command", input);
if (!result.success) {
  if (isInputValidationError(result.error)) {
    showValidationErrors(result.error.errors);
  } else {
    showGenericError(result.error);
  }
}

// Ou com try/catch
try {
  await commander.invoke("risky:command", input);
} catch (error) {
  if (isInputValidationError(error)) {
    // Campos faltando - pode redirecionar para coletar
    const missing = error.getMissingFields();
    await collectMissingFields(missing);
  }
}
```

---

## Roadmap: Middleware System

> Em desenvolvimento - veja `PROPOSAL-COMMANDER-INTERCEPTOR.md`

### Arquitetura Planejada

```
invoke(key, input, source)
│
├── 1. Command Lookup
├── 2. Build Context
│
├── 3. MIDDLEWARE PIPELINE ─────────────────────────── NOVO
│   ├── Global middlewares
│   ├── Category middlewares
│   ├── Pattern middlewares ("file:*")
│   ├── Specific middlewares ("file:save")
│   └── Custom filter middlewares
│
├── 4. Availability Check
├── 5. Input Validation
├── 6. Execute Handler
└── 7. Return Result
```

### API Planejada

```typescript
// Global
commander.use(loggingMiddleware);

// Por categoria
commander.use("admin", authMiddleware);

// Por pattern
commander.use("file:*", auditMiddleware);

// Por comando
commander.use("user:delete", confirmMiddleware);

// Por filtro
commander.use(cmd => cmd.tags?.includes("dangerous"), confirmMiddleware);

// Arrays
commander.use(["user:delete", "data:purge"], [authMiddleware, confirmMiddleware]);
```

---

## Referências

- [README.md](../README.md) - Documentação de uso
- [useInvoker-guide.md](./useInvoker-guide.md) - Guia detalhado de hooks
- [Middleware Proposal](./proposals/PROPOSAL-COMMANDER-INTERCEPTOR.md) - Proposta de middleware system

---

*Última atualização: 2025-12-03*
*Versão: 1.0.5*
