--- name: osint_obsidian_plugin lang: ts domain: osint version: 0.1.0 description: "Plugin de Obsidian (id osint-db) para el vault osint: ejecuta queries SQL y queries nombradas contra el service local osint_db (FastAPI + DuckDB) via HTTP y renderiza tablas de datos dentro de las notas mediante el code block osintdb. Plugin fino: no embebe ninguna base de datos." tags: [osint, obsidian, plugin, duckdb] uses_functions: [] uses_types: [] framework: "obsidian-plugin" entry_point: "main.ts" dir_path: "projects/osint/apps/osint_obsidian_plugin" repo_url: "https://gitea-dgg044oo04woo4ggcsws4gk0.organic-machine.com/dataforge/osint_obsidian_plugin" e2e_checks: - id: build cmd: "pnpm install --frozen-lockfile=false && pnpm build" timeout_s: 300 - id: artifact cmd: "test -f main.js" - id: tests cmd: "pnpm test" timeout_s: 60 --- # osint_obsidian_plugin Plugin de Obsidian para el vault `~/Obsidian/osint`. Es deliberadamente fino: no embebe DuckDB ni ninguna otra base de datos. Toda la lógica de datos vive en el service local `osint_db` (FastAPI, dueño de la DuckDB con datos OSINT), con el que el plugin habla por HTTP usando `requestUrl` de la API de Obsidian (evita CORS; nunca `fetch`). ## Qué hace 1. **Code block `osintdb`**: dentro de cualquier nota, un bloque de código con lenguaje `osintdb` se renderiza como una tabla de datos. Dos formas de contenido: - SQL crudo (el bloque entero es un SELECT, va a `POST /api/query`). - Directivas `clave: valor` al inicio del bloque: `query` (nombre de query guardada, va a `POST /api/query/named`), `max_rows` y `title`. 2. **Render seguro**: tabla HTML construida con `createEl` (los valores se insertan como texto, nunca como HTML crudo), header sticky, conteo de filas y nota "(truncado)" cuando el service recorta el resultado. Errores del service y service caído se muestran con mensajes claros, incluido el comando para arrancar `osint_db`. 3. **Botón "Refrescar"** por bloque: re-ejecuta la query sin recargar la nota. 4. **Enlaces a notas**: si una columna se llama `note_path` y el valor termina en `.md`, la celda se renderiza como enlace interno de Obsidian que abre la nota al hacer clic. 5. **Settings tab**: URL base del service (default `http://127.0.0.1:8771`) y `max_rows` por defecto (500), persistidos con `loadData`/`saveData`. 6. **Comando de paleta** "OSINT DB: Insertar bloque de query": inserta una plantilla de bloque `osintdb` en el editor. ## Ejemplo de bloque Forma con SQL crudo: ```osintdb title: Personas del caso X max_rows: 100 SELECT nombre, contexto, note_path FROM main.personas WHERE contexto = 'caso_x'; ``` Forma con query nombrada (definida en el service): ```osintdb query: personas_por_contexto max_rows: 100 ``` ## Contrato API del service osint_db Base URL por defecto: `http://127.0.0.1:8771`. El service responde siempre HTTP 200 y el plugin decide por el campo `status` del body. - `GET /api/health` → `{"status":"ok","db_path":"...","tables":N}` - `GET /api/tables` → listado de tablas con schema, kind, row_count y columnas. - `POST /api/query` body `{"sql":"SELECT ...","params":[],"max_rows":500}` → `{"status":"ok","columns":[...],"rows":[...],"row_count":N,"truncated":bool}` o `{"status":"error","error":"..."}`. - `GET /api/queries` → queries nombradas disponibles. - `POST /api/query/named` body `{"name":"...","max_rows":500}` → misma shape que `/api/query`. ## Cómo construir ```bash cd projects/osint/apps/osint_obsidian_plugin pnpm install pnpm build # tsc --noEmit + esbuild -> main.js pnpm test # tests del parser de bloques (node --test, sin Obsidian) ``` Requiere Node >= 23 para los tests (usa el type stripping nativo de `node --test` sobre archivos `.ts`). ## Cómo desplegar ```bash ./deploy.sh ``` Copia `manifest.json`, `main.js` y `styles.css` a `/home/enmanuel/Obsidian/osint/.obsidian/plugins/osint-db/`. **Activación manual (la hace el humano, no un agente):** tras el deploy, abrir Obsidian → Settings → Community plugins → activar "OSINT DB". Si Obsidian ya estaba abierto, hace falta recargar la app (Ctrl+R) o reiniciarla para que detecte el plugin nuevo o la versión nueva de `main.js`. ## Estructura - `main.ts` — plugin completo (processor, render, settings, comando). - `parse.ts` — parser puro del contenido de los bloques `osintdb` (testeable sin Obsidian). - `tests/parse.test.ts` — tests del parser con `node --test`. - `esbuild.config.mjs` — bundle CommonJS a `main.js` con `obsidian` como external. - `deploy.sh` — copia los artefactos al vault. ## Gotchas - El plugin no arranca el service: si `osint_db` no está corriendo, los bloques muestran "osint_db no responde en " con el comando de arranque como hint. - `main.js` es artefacto de build (gitignored): siempre `pnpm build` antes de `deploy.sh`. - `isDesktopOnly: true` en el manifest — el service es local, no tiene sentido en móvil.