feat(obsidian): add property frontmatter commands
Build and Push Docker Container / build-and-push (push) Successful in 4m27s
Build and Push Docker Container / build-and-push (push) Successful in 4m27s
- Expose Obsidian CLI property commands via the n8n Obsidian API node - Add a new Property resource with operations: Set, Read, Remove, List - Implement correct args mapping for property:set/property:read/property:remove/properties - Return raw CLI stdout for property read/list for easier downstream parsing - Update node README with frontmatter/property usage examples - Bump package version to 0.2.5
This commit is contained in:
@@ -16,6 +16,11 @@ Resources:
|
|||||||
- Delete
|
- Delete
|
||||||
- Rename
|
- Rename
|
||||||
- List Files
|
- List Files
|
||||||
|
- **Property**
|
||||||
|
- Set
|
||||||
|
- Read
|
||||||
|
- Remove
|
||||||
|
- List
|
||||||
- **Daily Note**
|
- **Daily Note**
|
||||||
- Append
|
- Append
|
||||||
- Prepend
|
- Prepend
|
||||||
@@ -51,6 +56,29 @@ Raw command example:
|
|||||||
["vault=work", "read", "path=Inbox/Note.md"]
|
["vault=work", "read", "path=Inbox/Note.md"]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Properties / frontmatter
|
||||||
|
The official Obsidian CLI supports property/frontmatter commands. The n8n node exposes them as the **Property** resource:
|
||||||
|
|
||||||
|
- **Set** sends `property:set path=<note> name=<property> value=<value> type=<type>`
|
||||||
|
- **Read** sends `property:read path=<note> name=<property>`
|
||||||
|
- **Remove** sends `property:remove path=<note> name=<property>`
|
||||||
|
- **List** sends `properties name=<optional> format=<yaml|json|tsv>`
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
```text
|
||||||
|
path=00 Kontext/Feedback Browser CLI Tests.md
|
||||||
|
name=tags
|
||||||
|
value=kontext, feedback-browser-cli-tests
|
||||||
|
type=list
|
||||||
|
```
|
||||||
|
|
||||||
|
```text
|
||||||
|
path=00 Kontext/Feedback Browser CLI Tests.md
|
||||||
|
name=date
|
||||||
|
value=2026-06-24
|
||||||
|
type=date
|
||||||
|
```
|
||||||
|
|
||||||
## Local install in self-hosted n8n
|
## Local install in self-hosted n8n
|
||||||
From this repo:
|
From this repo:
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ export class ObsidianApi implements INodeType {
|
|||||||
options: [
|
options: [
|
||||||
{ name: 'Daily Note', value: 'daily' },
|
{ name: 'Daily Note', value: 'daily' },
|
||||||
{ name: 'Note', value: 'note' },
|
{ name: 'Note', value: 'note' },
|
||||||
|
{ name: 'Property', value: 'property' },
|
||||||
{ name: 'Raw Command', value: 'raw' },
|
{ name: 'Raw Command', value: 'raw' },
|
||||||
{ name: 'Search', value: 'search' },
|
{ name: 'Search', value: 'search' },
|
||||||
{ name: 'Vault', value: 'vault' },
|
{ name: 'Vault', value: 'vault' },
|
||||||
@@ -129,6 +130,78 @@ export class ObsidianApi implements INodeType {
|
|||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Property operations
|
||||||
|
{
|
||||||
|
displayName: 'Operation',
|
||||||
|
name: 'operation',
|
||||||
|
type: 'options',
|
||||||
|
noDataExpression: true,
|
||||||
|
displayOptions: { show: { resource: ['property'] } },
|
||||||
|
options: [
|
||||||
|
{ name: 'List', value: 'properties' },
|
||||||
|
{ name: 'Read', value: 'propertyRead' },
|
||||||
|
{ name: 'Remove', value: 'propertyRemove' },
|
||||||
|
{ name: 'Set', value: 'propertySet' },
|
||||||
|
],
|
||||||
|
default: 'propertySet',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Path',
|
||||||
|
name: 'propertyPath',
|
||||||
|
type: 'string',
|
||||||
|
displayOptions: { show: { resource: ['property'], operation: ['propertyRead', 'propertyRemove', 'propertySet'] } },
|
||||||
|
default: '',
|
||||||
|
placeholder: 'Inbox/Note.md',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Name',
|
||||||
|
name: 'propertyName',
|
||||||
|
type: 'string',
|
||||||
|
displayOptions: { show: { resource: ['property'], operation: ['propertyRead', 'propertyRemove', 'propertySet', 'properties'] } },
|
||||||
|
default: '',
|
||||||
|
placeholder: 'tags',
|
||||||
|
description: 'Frontmatter/property name, e.g. tags, date, description',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Value',
|
||||||
|
name: 'propertyValue',
|
||||||
|
type: 'string',
|
||||||
|
displayOptions: { show: { resource: ['property'], operation: ['propertySet'] } },
|
||||||
|
default: '',
|
||||||
|
placeholder: 'kontext, feedback-browser-cli-tests',
|
||||||
|
description: 'Value passed to the official CLI property:set command',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Type',
|
||||||
|
name: 'propertyType',
|
||||||
|
type: 'options',
|
||||||
|
displayOptions: { show: { resource: ['property'], operation: ['propertySet'] } },
|
||||||
|
options: [
|
||||||
|
{ name: 'Text', value: 'text' },
|
||||||
|
{ name: 'List', value: 'list' },
|
||||||
|
{ name: 'Number', value: 'number' },
|
||||||
|
{ name: 'Checkbox', value: 'checkbox' },
|
||||||
|
{ name: 'Date', value: 'date' },
|
||||||
|
{ name: 'Date Time', value: 'datetime' },
|
||||||
|
],
|
||||||
|
default: 'text',
|
||||||
|
description: 'Obsidian property type. Use List for tags and Date for date.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Format',
|
||||||
|
name: 'propertiesFormat',
|
||||||
|
type: 'options',
|
||||||
|
displayOptions: { show: { resource: ['property'], operation: ['properties'] } },
|
||||||
|
options: [
|
||||||
|
{ name: 'YAML', value: 'yaml' },
|
||||||
|
{ name: 'JSON', value: 'json' },
|
||||||
|
{ name: 'TSV', value: 'tsv' },
|
||||||
|
],
|
||||||
|
default: 'yaml',
|
||||||
|
},
|
||||||
|
|
||||||
// Search operations
|
// Search operations
|
||||||
{
|
{
|
||||||
displayName: 'Operation',
|
displayName: 'Operation',
|
||||||
@@ -247,6 +320,10 @@ export class ObsidianApi implements INodeType {
|
|||||||
args = buildSearchArgs(this, operation, itemIndex);
|
args = buildSearchArgs(this, operation, itemIndex);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'property': {
|
||||||
|
args = buildPropertyArgs(this, operation, itemIndex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'vault': {
|
case 'vault': {
|
||||||
args = buildVaultArgs(this, operation, itemIndex, additionalFields);
|
args = buildVaultArgs(this, operation, itemIndex, additionalFields);
|
||||||
break;
|
break;
|
||||||
@@ -293,6 +370,15 @@ export class ObsidianApi implements INodeType {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Properties: keep CLI output because read/list return useful data.
|
||||||
|
if (resource === 'property' && (operation === 'propertyRead' || operation === 'properties')) {
|
||||||
|
const out: any = { content: stdout };
|
||||||
|
if (result.stderr) out.stderr = result.stderr;
|
||||||
|
if (result.timed_out) out.timed_out = result.timed_out;
|
||||||
|
returnData.push({ json: out, pairedItem: { item: itemIndex } });
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// vault and vaults are parsed as structured JSON
|
// vault and vaults are parsed as structured JSON
|
||||||
const parsed = (result as any).parsed_stdout;
|
const parsed = (result as any).parsed_stdout;
|
||||||
if (parsed) {
|
if (parsed) {
|
||||||
@@ -370,6 +456,34 @@ function buildSearchArgs(context: IExecuteFunctions, operation: string, itemInde
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildPropertyArgs(context: IExecuteFunctions, operation: string, itemIndex: number): string[] {
|
||||||
|
const path = context.getNodeParameter('propertyPath', itemIndex, '') as string;
|
||||||
|
const name = context.getNodeParameter('propertyName', itemIndex, '') as string;
|
||||||
|
|
||||||
|
switch (operation) {
|
||||||
|
case 'properties':
|
||||||
|
return compactArgs([
|
||||||
|
'properties',
|
||||||
|
kv('name', name),
|
||||||
|
kv('format', context.getNodeParameter('propertiesFormat', itemIndex) as string),
|
||||||
|
]);
|
||||||
|
case 'propertyRead':
|
||||||
|
return compactArgs(['property:read', kv('path', path), kv('name', name)]);
|
||||||
|
case 'propertyRemove':
|
||||||
|
return compactArgs(['property:remove', kv('path', path), kv('name', name)]);
|
||||||
|
case 'propertySet':
|
||||||
|
return compactArgs([
|
||||||
|
'property:set',
|
||||||
|
kv('path', path),
|
||||||
|
kv('name', name),
|
||||||
|
kv('value', context.getNodeParameter('propertyValue', itemIndex) as string),
|
||||||
|
kv('type', context.getNodeParameter('propertyType', itemIndex) as string),
|
||||||
|
]);
|
||||||
|
default:
|
||||||
|
throw new NodeOperationError(context.getNode(), `Unsupported property operation: ${operation}`, { itemIndex });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function buildVaultArgs(context: IExecuteFunctions, operation: string, itemIndex: number, additionalFields: Record<string, unknown>): string[] {
|
function buildVaultArgs(context: IExecuteFunctions, operation: string, itemIndex: number, additionalFields: Record<string, unknown>): string[] {
|
||||||
switch (operation) {
|
switch (operation) {
|
||||||
case 'vaultInfo':
|
case 'vaultInfo':
|
||||||
|
|||||||
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "n8n-nodes-obsidian-cli-api",
|
"name": "n8n-nodes-obsidian-cli-api",
|
||||||
"version": "0.2.4",
|
"version": "0.2.5",
|
||||||
"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.4",
|
"version": "0.2.5",
|
||||||
"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.4",
|
"version": "0.2.5",
|
||||||
"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",
|
||||||
|
|||||||
Reference in New Issue
Block a user