fix: always return minimal n8n output
Build and Push Docker Container / build-and-push (push) Successful in 4m36s
Build and Push Docker Container / build-and-push (push) Successful in 4m36s
- Node now outputs only stdout (parsed or raw) plus optional stderr - Keep output stable across all operations to simplify n8n mappings - Trim trailing newlines from runner stdout/stderr for cleaner display - Bump server version to 1.0.3 to ship runner/output changes - Bump n8n node package via versioned build artifacts
This commit is contained in:
+2
-2
@@ -36,8 +36,8 @@ async def execute_command(args:list[str], cwd:Path, stdin:str|None, timeout:floa
|
|||||||
timed_out = True
|
timed_out = True
|
||||||
|
|
||||||
duration_ms = int((time.perf_counter() - started) * 1000)
|
duration_ms = int((time.perf_counter() - started) * 1000)
|
||||||
stdout = stdout_b.decode(errors="replace")
|
stdout = stdout_b.decode(errors="replace").rstrip()
|
||||||
stderr = stderr_b.decode(errors="replace")
|
stderr = stderr_b.decode(errors="replace").rstrip()
|
||||||
exit_code = process.returncode if process.returncode is not None else -1
|
exit_code = process.returncode if process.returncode is not None else -1
|
||||||
|
|
||||||
if timed_out:
|
if timed_out:
|
||||||
|
|||||||
@@ -260,7 +260,16 @@ export class ObsidianApi implements INodeType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const result = await executeObsidianCommand(this, itemIndex, args, { vault, timeout });
|
const result = await executeObsidianCommand(this, itemIndex, args, { vault, timeout });
|
||||||
returnData.push({ json: result, pairedItem: { item: itemIndex } });
|
|
||||||
|
// Always keep n8n output minimal/clean.
|
||||||
|
// - Prefer parsed stdout (e.g. vault/vaults)
|
||||||
|
// - Otherwise keep stdout as-is
|
||||||
|
const stdoutValue = (result as any).parsed_stdout ?? result.stdout;
|
||||||
|
const out: any = { stdout: stdoutValue };
|
||||||
|
if (result.stderr) out.stderr = result.stderr;
|
||||||
|
if (result.timed_out) out.timed_out = result.timed_out;
|
||||||
|
|
||||||
|
returnData.push({ json: out, pairedItem: { item: itemIndex } });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (this.continueOnFail()) {
|
if (this.continueOnFail()) {
|
||||||
const message = error instanceof Error ? error.message : String(error);
|
const message = error instanceof Error ? error.message : String(error);
|
||||||
|
|||||||
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "n8n-nodes-obsidian-cli-api",
|
"name": "n8n-nodes-obsidian-cli-api",
|
||||||
"version": "0.2.1",
|
"version": "0.2.2",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "n8n-nodes-obsidian-cli-api",
|
"name": "n8n-nodes-obsidian-cli-api",
|
||||||
"version": "0.2.1",
|
"version": "0.2.2",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^24.0.0",
|
"@types/node": "^24.0.0",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "n8n-nodes-obsidian-cli-api",
|
"name": "n8n-nodes-obsidian-cli-api",
|
||||||
"version": "0.2.1",
|
"version": "0.2.2",
|
||||||
"description": "n8n community nodes for the Obsidian API Docker service backed by the official Obsidian CLI.",
|
"description": "n8n community nodes for the Obsidian API Docker service backed by the official Obsidian CLI.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"homepage": "https://git.yiprawr.dev/Docker/obsidian-api",
|
"homepage": "https://git.yiprawr.dev/Docker/obsidian-api",
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ export interface ObsidianCommandResult extends IDataObject {
|
|||||||
stderr: string;
|
stderr: string;
|
||||||
duration_ms: number;
|
duration_ms: number;
|
||||||
timed_out: boolean;
|
timed_out: boolean;
|
||||||
|
parsed_stdout?: IDataObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ObsidianCredentials extends IDataObject {
|
export interface ObsidianCredentials extends IDataObject {
|
||||||
@@ -72,6 +73,9 @@ export async function executeObsidianCommand(
|
|||||||
}
|
}
|
||||||
const result = normalizeCommandResult(response);
|
const result = normalizeCommandResult(response);
|
||||||
|
|
||||||
|
const parsed = maybeParseStdout(result);
|
||||||
|
if (parsed) result.parsed_stdout = parsed;
|
||||||
|
|
||||||
if (result.exit_code !== 0) {
|
if (result.exit_code !== 0) {
|
||||||
throw new NodeOperationError(
|
throw new NodeOperationError(
|
||||||
context.getNode(),
|
context.getNode(),
|
||||||
@@ -139,6 +143,42 @@ function extractErrorMessage(body: unknown): string {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function maybeParseStdout(result: ObsidianCommandResult): IDataObject | undefined {
|
||||||
|
const lastArg = result.command[result.command.length - 1];
|
||||||
|
if (lastArg !== 'vault' && lastArg !== 'vaults') return undefined;
|
||||||
|
|
||||||
|
// Obsidian CLI prints either:
|
||||||
|
// vault:
|
||||||
|
// key<TAB>value\nkey<TAB>value\n...
|
||||||
|
// vaults:
|
||||||
|
// often one vault per line (names) or a similar tabular output.
|
||||||
|
const lines = (result.stdout || '')
|
||||||
|
.split(/\r?\n/)
|
||||||
|
.map((l) => l.trim())
|
||||||
|
.filter(Boolean);
|
||||||
|
|
||||||
|
if (!lines.length) return undefined;
|
||||||
|
|
||||||
|
const isKv = lines.some((l) => l.includes('\t'));
|
||||||
|
if (!isKv && lastArg === 'vaults') {
|
||||||
|
return { vaults: lines };
|
||||||
|
}
|
||||||
|
|
||||||
|
const kv: Record<string, string | number> = {};
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (/^-?\d+$/.test(rawValue)) kv[key] = Number(rawValue);
|
||||||
|
else kv[key] = rawValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.keys(kv).length ? kv : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeCommandResult(response: unknown): ObsidianCommandResult {
|
function normalizeCommandResult(response: unknown): ObsidianCommandResult {
|
||||||
const data = extractResponseBody(response);
|
const data = extractResponseBody(response);
|
||||||
const result = typeof data === 'string' ? JSON.parse(data) : data;
|
const result = typeof data === 'string' ? JSON.parse(data) : data;
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "obsidian-api"
|
name = "obsidian-api"
|
||||||
version = "1.0.2"
|
version = "1.0.3"
|
||||||
description = "HTTP API wrapper for running Obsidian CLI commands from n8n, SDKs, or agent harnesses."
|
description = "HTTP API wrapper for running Obsidian CLI commands from n8n, SDKs, or agent harnesses."
|
||||||
requires-python = ">=3.14"
|
requires-python = ">=3.14"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "obsidian-api"
|
name = "obsidian-api"
|
||||||
version = "1.0.0"
|
version = "1.0.3"
|
||||||
source = { virtual = "." }
|
source = { virtual = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "starlette" },
|
{ name = "starlette" },
|
||||||
|
|||||||
Reference in New Issue
Block a user