# SimpleNote CLI - Protocolo de Comunicación ## 1. Overview El CLI (`simplenote-cli`) se comunica con el servidor (`simplenote-web`) exclusivamente vía HTTP REST usando el API documentado en `api-spec.yaml`. No hay comunicación peer-to-peer ni protocolos binarios. Todo es JSON sobre HTTP. ``` ┌──────────────────┐ HTTP/REST ┌─────────────────┐ │ simplenote-cli │ ◄──────────────────► │ simplenote-web │ │ (Commander.js) │ Bearer token auth │ (Express.js) │ └──────────────────┘ └─────────────────┘ │ │ └──── ~/.config/simplenote/config.json ──┘ ``` ## 2. Cliente HTTP ### 2.1 Clase `SimpleNoteClient` ```javascript // src/api/client.js const axios = require('axios'); class SimpleNoteClient { constructor({ baseUrl, token }) { this.baseUrl = baseUrl.replace(/\/$/, ''); // strip trailing slash this.token = token; this._axios = axios.create({ baseURL: this.baseUrl, timeout: 10000, headers: { 'Content-Type': 'application/json' } }); } _authHeaders() { return this.token ? { Authorization: `Bearer ${this.token}` } : {}; } async _request(method, path, data) { try { const res = await this._axios.request({ method, url: path, data, headers: this._authHeaders() }); return res.data; } catch (err) { if (err.response) { const msg = err.response.data?.error || err.message; throw new Error(`API Error ${err.response.status}: ${msg}`); } throw err; } } // Auth async verifyToken() { return this._request('GET', '/auth/verify'); } // Documents async listDocuments(params) { const qs = new URLSearchParams(params).toString(); return this._request('GET', `/documents${qs ? '?' + qs : ''}`); } async getDocument(id) { return this._request('GET', `/documents/${id}`); } async createDocument(data) { return this._request('POST', '/documents', data); } async updateDocument(id, data) { return this._request('PUT', `/documents/${id}`, data); } async deleteDocument(id) { return this._request('DELETE', `/documents/${id}`); } async exportDocument(id) { return this._request('GET', `/documents/${id}/export`); } // Documents > Tags async addTagsToDocument(id, tags) { return this._request('POST', `/documents/${id}/tags`, { tags }); } // Libraries async listLibraries() { return this._request('GET', '/libraries'); } async getLibrary(id) { return this._request('GET', `/libraries/${id}`); } async createLibrary(data) { return this._request('POST', '/libraries', data); } async getLibraryTree(id) { return this._request('GET', `/libraries/${id}/tree`); } async listLibraryDocuments(id) { return this._request('GET', `/libraries/${id}/documents`); } // Tags async listTags() { return this._request('GET', '/tags'); } async getTagDocuments(tag) { return this._request('GET', `/tags/${tag}`); } } ``` ## 3. Flujo de Auth ### 3.1 Login Inicial ```bash simplenote auth login snk_a1b2c3d4e5f6... ``` Flujo: 1. CLI guarda token en `~/.config/simplenote/config.json` 2. CLI llama `GET /api/v1/auth/verify` para validar 3. Si 200 → login exitoso. Si 401 → token inválido. ### 3.2 Requests Subsecuentes Todas las requests incluyen: ``` Authorization: Bearer ``` ### 3.3 Verificación de Status ```bash simplenote auth status ``` → `GET /auth/verify` → muestra si token es válido. ## 4. Comandos CLI Detallados ### 4.1 Documents ```bash # Listar con filtros simplenote doc list --tag backend --library 550e8400... --type requirement simplenote doc list --tag api --limit 10 # Ver documento simplenote doc get 770e8400-e29b-41d4-a716-446655440002 # Crear simplenote doc create \ --title "API Authentication" \ --content "# API Authentication\n\n..." \ --tags "backend,api,auth" \ --type requirement \ --priority high \ --library 550e8400-e29b-41d4-a716-446655440000 # Actualizar simplenote doc update 770e8400... --title "Nuevo título" --content "..." simplenote doc update 770e8400... --status approved # Eliminar simplenote doc delete 770e8400... # Exportar como markdown simplenote doc export 770e8400... # Agregar tags simplenote doc add-tags 770e8400... --tags "new-tag,another" ``` ### 4.2 Libraries ```bash # Listar librerías raíz simplenote lib list # Listar con padre simplenote lib list --parent 550e8400... # Ver contenido simplenote lib get 550e8400... # Crear simplenote lib create --name "API Specs" simplenote lib create --name "Sub Librería" --parent 550e8400... # Ver árbol completo simplenote lib tree 550e8400... ``` ### 4.3 Tags ```bash # Listar todos los tags simplenote tag list # Ver docs con tag simplenote tag docs backend ``` ### 4.4 Auth ```bash # Login con token simplenote auth login snk_xxxxx # Verificar status simplenote auth status ``` ## 5. Manejo de Errores ```javascript // Errores de API se transforman en mensajes claros try { await client.getDocument('non-existent-id'); } catch (err) { console.error(err.message); // "API Error 404: Document not found" } ``` Códigos de error CLI: - `1` — Error general (network, parse, etc) - `2` — Token inválido / auth fallida - `3` — Recurso no encontrado (404) - `4` — Validación de input ## 6. Configuración de Conexión ```javascript // ~/.config/simplenote/config.json { "apiUrl": "http://localhost:3000/api/v1", "token": "snk_xxxxx", "activeLibrary": "550e8400-e29b-41d4-a716-446655440000" } ``` Override por línea de comandos: ```bash simplenote --api-url http://custom:3000/api/v1 doc list ``` ## 7. Dependencias CLI ```json // package.json { "dependencies": { "commander": "^11.1.0", "axios": "^1.6.0", "chalk": "^5.3.0", "inquirer": "^9.2.0" } } ``` ## 8. Ejemplo de Sesión Completa ```bash $ simplenote auth login snk_a1b2c3d4e5f6 ✓ Token verified. Logged in. $ simplenote lib list [ { "id": "550e8400...", "name": "Backend Requirements", "documentCount": 5 } ] $ simplenote doc create \ --title "Token Auth" \ --tags "backend,auth" \ --type requirement \ --library 550e8400... { "id": "770e8400...", "title": "Token Auth", "tags": ["backend", "auth"], ... } $ simplenote tag docs backend [ { "id": "770e8400...", "title": "Token Auth", ... } ] $ simplenote doc get 770e8400... # Muestra documento formateado con content + metadata ```