fix: serialize property writes and expose n8n results
Build and Push Docker Container / build-and-push (push) Successful in 3m31s

- Serialize property set and remove commands per vault note to avoid lost frontmatter writes.
- Wait briefly for successful property writes to hit disk before releasing the note lock.
- Return property path, name, value, type, operation, and ok status in n8n outputs.
- Include property details on continue-on-fail errors so failed items are visible in n8n.
- Bump obsidian-api to 1.0.7 and n8n-nodes-obsidian-cli-api to 0.2.8.
- Add regression coverage for concurrent property writes to the same note.
This commit is contained in:
2026-09-15 09:43:24 +02:00
parent 81a27f3e9b
commit e115698e92
9 changed files with 272 additions and 72 deletions
@@ -31,7 +31,20 @@ export class ObsidianApi implements INodeType {
} catch (error) {
if (this.continueOnFail()) {
const message = error instanceof Error ? error.message : String(error);
returnData.push({ json: { error: message }, pairedItem: { item: itemIndex } });
const resource = this.getNodeParameter('resource', itemIndex, '') as string;
const operation = this.getNodeParameter('operation', itemIndex, '') as string;
const failure = resource === 'property'
? {
ok: false,
operation,
path: this.getNodeParameter('propertyPath', itemIndex, '') as string,
property: this.getNodeParameter('propertyName', itemIndex, '') as string,
value: this.getNodeParameter('propertyValue', itemIndex, '') as string,
type: this.getNodeParameter('propertyType', itemIndex, '') as string,
error: message,
}
: { ok: false, error: message };
returnData.push({ json: failure, pairedItem: { item: itemIndex } });
continue;
}
throw error;
@@ -1,6 +1,7 @@
import type { IDataObject, INodeExecutionData } from 'n8n-workflow';
import type { ObsidianCommandResult } from '../../shared/ObsidianApiClient';
import { propertyDetailsFromArgs } from './propertyOutput';
export function outputForResult(result: ObsidianCommandResult, resource: string, operation: string, itemIndex: number): INodeExecutionData {
const stdout = result.stdout ?? '';
@@ -17,6 +18,9 @@ export function outputForResult(result: ObsidianCommandResult, resource: string,
if (resource === 'property' && (operation === 'propertyRead' || operation === 'properties')) {
return paired({ content: stdout }, result, itemIndex);
}
if (resource === 'property' && (operation === 'propertySet' || operation === 'propertyRemove')) {
return paired({ ok: true, operation, ...propertyDetailsFromArgs(result.command) }, result, itemIndex);
}
const parsed = result.parsed_stdout;
if (parsed) return paired(parsed, result, itemIndex);
@@ -0,0 +1,34 @@
import type { IDataObject } from 'n8n-workflow';
function parseArg(arg: string): [string, string] | undefined {
const index = arg.indexOf('=');
if (index <= 0) return undefined;
return [arg.slice(0, index), arg.slice(index + 1)];
}
export function propertyDetailsFromArgs(args: string[]): IDataObject {
const details: IDataObject = {};
for (const arg of args) {
const parsed = parseArg(arg);
if (!parsed) continue;
const [key, value] = parsed;
switch (key) {
case 'path':
details.path = value;
break;
case 'name':
details.property = value;
break;
case 'value':
details.value = value;
break;
case 'type':
details.type = value;
break;
}
}
return details;
}
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "n8n-nodes-obsidian-cli-api",
"version": "0.2.7",
"version": "0.2.8",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "n8n-nodes-obsidian-cli-api",
"version": "0.2.7",
"version": "0.2.8",
"license": "MIT",
"devDependencies": {
"@types/node": "^24.0.0",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "n8n-nodes-obsidian-cli-api",
"version": "0.2.7",
"version": "0.2.8",
"description": "n8n community nodes for the Obsidian API Docker service backed by the official Obsidian CLI.",
"license": "MIT",
"homepage": "https://git.yiprawr.dev/Docker/obsidian-api",