Files
simplenote-web/cli-protocol.md
Bulma 90e4dd0807 feat(architecture): add complete technical architecture for SimpleNote
- ARCHITECTURE.md: main architecture document
- api-spec.yaml: full OpenAPI 3.0 spec
- folder-structure.md: detailed folder layout
- data-format.md: JSON schemas for .meta.json, .library.json, .tag-index.json
- env-template.md: environment variables documentation
- cli-protocol.md: CLI-to-API communication protocol
2026-03-28 03:18:25 +00:00

275 lines
6.5 KiB
Markdown

# 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 <token>
```
### 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
```