import type { IDataObject } from 'n8n-workflow'; import type { ObsidianCommandResult } from './ObsidianApiClient'; export function normalizeCommandResult(response: unknown): ObsidianCommandResult { const data = extractResponseBody(response); const result = typeof data === 'string' ? JSON.parse(data) : data; if (!isRecord(result)) { throw new Error('Obsidian API returned a non-object response'); } return { id: String(result.id ?? ''), command: Array.isArray(result.command) ? result.command.map(String) : [], cwd: String(result.cwd ?? ''), exit_code: Number(result.exit_code ?? 0), stdout: String(result.stdout ?? ''), stderr: String(result.stderr ?? ''), duration_ms: Number(result.duration_ms ?? 0), timed_out: Boolean(result.timed_out), }; } export function maybeParseStdout(result: ObsidianCommandResult): IDataObject | undefined { const cmd = result.command; const hasVault = cmd.includes('vault'); const hasVaults = cmd.includes('vaults'); if (!hasVault && !hasVaults) return undefined; const lines = (result.stdout || '') .split(/\r?\n/) .map((l) => l.trim()) .filter(Boolean); if (!lines.length) return undefined; if (hasVaults) return parseVaultsOutput(lines); return parseVaultOutput(lines); } function parseVaultsOutput(lines: string[]): IDataObject { const vaults: Array<{ name: string; path: string }> = []; for (const line of lines) { const parts = line.split('\t'); if (parts.length < 2) continue; const name = parts[0].trim(); const path = parts.slice(1).join('\t').trim(); if (!name || !path) continue; vaults.push({ name, path }); } return vaults.length ? { vaults } : { vaults: lines }; } function parseVaultOutput(lines: string[]): IDataObject | undefined { const kv: Record = {}; for (const line of lines) { const parts = line.split('\t'); if (parts.length < 2) continue; const key = parts[0].trim(); const rawValue = parts.slice(1).join('\t').trim(); if (!key || !rawValue) continue; kv[key] = /^-?\d+$/.test(rawValue) ? Number(rawValue) : rawValue; } return Object.keys(kv).length ? kv : undefined; } function extractResponseBody(response: unknown): unknown { if (!isRecord(response)) return response; if ('body' in response) return response.body; if ('data' in response) return response.data; return response; } function isRecord(value: unknown): value is Record { return typeof value === 'object' && value !== null; }