Initial commit
This commit is contained in:
800
skills/n8n-node-configuration/DEPENDENCIES.md
Normal file
800
skills/n8n-node-configuration/DEPENDENCIES.md
Normal file
@@ -0,0 +1,800 @@
|
||||
# Property Dependencies Guide
|
||||
|
||||
Deep dive into n8n property dependencies and displayOptions mechanism.
|
||||
|
||||
---
|
||||
|
||||
## What Are Property Dependencies?
|
||||
|
||||
**Definition**: Rules that control when fields are visible or required based on other field values.
|
||||
|
||||
**Mechanism**: `displayOptions` in node schema
|
||||
|
||||
**Purpose**:
|
||||
- Show relevant fields only
|
||||
- Hide irrelevant fields
|
||||
- Simplify configuration UX
|
||||
- Prevent invalid configurations
|
||||
|
||||
---
|
||||
|
||||
## displayOptions Structure
|
||||
|
||||
### Basic Format
|
||||
|
||||
```javascript
|
||||
{
|
||||
"name": "fieldName",
|
||||
"type": "string",
|
||||
"displayOptions": {
|
||||
"show": {
|
||||
"otherField": ["value1", "value2"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Translation**: Show `fieldName` when `otherField` equals "value1" OR "value2"
|
||||
|
||||
### Show vs Hide
|
||||
|
||||
#### show (Most Common)
|
||||
|
||||
**Show field when condition matches**:
|
||||
```javascript
|
||||
{
|
||||
"name": "body",
|
||||
"displayOptions": {
|
||||
"show": {
|
||||
"sendBody": [true]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Meaning**: Show `body` when `sendBody = true`
|
||||
|
||||
#### hide (Less Common)
|
||||
|
||||
**Hide field when condition matches**:
|
||||
```javascript
|
||||
{
|
||||
"name": "advanced",
|
||||
"displayOptions": {
|
||||
"hide": {
|
||||
"simpleMode": [true]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Meaning**: Hide `advanced` when `simpleMode = true`
|
||||
|
||||
### Multiple Conditions (AND Logic)
|
||||
|
||||
```javascript
|
||||
{
|
||||
"name": "body",
|
||||
"displayOptions": {
|
||||
"show": {
|
||||
"sendBody": [true],
|
||||
"method": ["POST", "PUT", "PATCH"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Meaning**: Show `body` when:
|
||||
- `sendBody = true` AND
|
||||
- `method IN (POST, PUT, PATCH)`
|
||||
|
||||
**All conditions must match** (AND logic)
|
||||
|
||||
### Multiple Values (OR Logic)
|
||||
|
||||
```javascript
|
||||
{
|
||||
"name": "someField",
|
||||
"displayOptions": {
|
||||
"show": {
|
||||
"method": ["POST", "PUT", "PATCH"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Meaning**: Show `someField` when:
|
||||
- `method = POST` OR
|
||||
- `method = PUT` OR
|
||||
- `method = PATCH`
|
||||
|
||||
**Any value matches** (OR logic)
|
||||
|
||||
---
|
||||
|
||||
## Common Dependency Patterns
|
||||
|
||||
### Pattern 1: Boolean Toggle
|
||||
|
||||
**Use case**: Optional feature flag
|
||||
|
||||
**Example**: HTTP Request sendBody
|
||||
```javascript
|
||||
// Field: sendBody (boolean)
|
||||
{
|
||||
"name": "sendBody",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
|
||||
// Field: body (depends on sendBody)
|
||||
{
|
||||
"name": "body",
|
||||
"displayOptions": {
|
||||
"show": {
|
||||
"sendBody": [true]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Flow**:
|
||||
1. User sees sendBody checkbox
|
||||
2. When checked → body field appears
|
||||
3. When unchecked → body field hides
|
||||
|
||||
### Pattern 2: Resource/Operation Cascade
|
||||
|
||||
**Use case**: Different operations show different fields
|
||||
|
||||
**Example**: Slack message operations
|
||||
```javascript
|
||||
// Operation: post
|
||||
{
|
||||
"name": "channel",
|
||||
"displayOptions": {
|
||||
"show": {
|
||||
"resource": ["message"],
|
||||
"operation": ["post"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Operation: update
|
||||
{
|
||||
"name": "messageId",
|
||||
"displayOptions": {
|
||||
"show": {
|
||||
"resource": ["message"],
|
||||
"operation": ["update"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Flow**:
|
||||
1. User selects resource="message"
|
||||
2. User selects operation="post" → sees channel
|
||||
3. User changes to operation="update" → channel hides, messageId shows
|
||||
|
||||
### Pattern 3: Type-Specific Configuration
|
||||
|
||||
**Use case**: Different types need different fields
|
||||
|
||||
**Example**: IF node conditions
|
||||
```javascript
|
||||
// String operations
|
||||
{
|
||||
"name": "value2",
|
||||
"displayOptions": {
|
||||
"show": {
|
||||
"conditions.string.0.operation": ["equals", "notEquals", "contains"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unary operations (isEmpty) don't show value2
|
||||
{
|
||||
"displayOptions": {
|
||||
"hide": {
|
||||
"conditions.string.0.operation": ["isEmpty", "isNotEmpty"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Pattern 4: Method-Specific Fields
|
||||
|
||||
**Use case**: HTTP methods have different options
|
||||
|
||||
**Example**: HTTP Request
|
||||
```javascript
|
||||
// Query parameters (all methods can have)
|
||||
{
|
||||
"name": "queryParameters",
|
||||
"displayOptions": {
|
||||
"show": {
|
||||
"sendQuery": [true]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Body (only certain methods)
|
||||
{
|
||||
"name": "body",
|
||||
"displayOptions": {
|
||||
"show": {
|
||||
"sendBody": [true],
|
||||
"method": ["POST", "PUT", "PATCH", "DELETE"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Using get_property_dependencies
|
||||
|
||||
### Basic Usage
|
||||
|
||||
```javascript
|
||||
const deps = get_property_dependencies({
|
||||
nodeType: "nodes-base.httpRequest"
|
||||
});
|
||||
```
|
||||
|
||||
### Example Response
|
||||
|
||||
```javascript
|
||||
{
|
||||
"nodeType": "n8n-nodes-base.httpRequest",
|
||||
"dependencies": {
|
||||
"body": {
|
||||
"shows_when": {
|
||||
"sendBody": [true],
|
||||
"method": ["POST", "PUT", "PATCH", "DELETE"]
|
||||
},
|
||||
"required_when_shown": true
|
||||
},
|
||||
"queryParameters": {
|
||||
"shows_when": {
|
||||
"sendQuery": [true]
|
||||
},
|
||||
"required_when_shown": false
|
||||
},
|
||||
"headerParameters": {
|
||||
"shows_when": {
|
||||
"sendHeaders": [true]
|
||||
},
|
||||
"required_when_shown": false
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### When to Use
|
||||
|
||||
**✅ Use when**:
|
||||
- Validation fails with "missing field" but you don't see that field
|
||||
- A field appears/disappears unexpectedly
|
||||
- You need to understand what controls field visibility
|
||||
- Building dynamic configuration tools
|
||||
|
||||
**❌ Don't use when**:
|
||||
- Simple configuration (use get_node_essentials)
|
||||
- Just starting configuration
|
||||
- Field requirements are obvious
|
||||
|
||||
---
|
||||
|
||||
## Complex Dependency Examples
|
||||
|
||||
### Example 1: HTTP Request Complete Flow
|
||||
|
||||
**Scenario**: Configuring POST with JSON body
|
||||
|
||||
**Step 1**: Set method
|
||||
```javascript
|
||||
{
|
||||
"method": "POST"
|
||||
// → sendBody becomes visible
|
||||
}
|
||||
```
|
||||
|
||||
**Step 2**: Enable body
|
||||
```javascript
|
||||
{
|
||||
"method": "POST",
|
||||
"sendBody": true
|
||||
// → body field becomes visible AND required
|
||||
}
|
||||
```
|
||||
|
||||
**Step 3**: Configure body
|
||||
```javascript
|
||||
{
|
||||
"method": "POST",
|
||||
"sendBody": true,
|
||||
"body": {
|
||||
"contentType": "json"
|
||||
// → content field becomes visible AND required
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Step 4**: Add content
|
||||
```javascript
|
||||
{
|
||||
"method": "POST",
|
||||
"sendBody": true,
|
||||
"body": {
|
||||
"contentType": "json",
|
||||
"content": {
|
||||
"name": "John",
|
||||
"email": "john@example.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
// ✅ Valid!
|
||||
```
|
||||
|
||||
**Dependency chain**:
|
||||
```
|
||||
method=POST
|
||||
→ sendBody visible
|
||||
→ sendBody=true
|
||||
→ body visible + required
|
||||
→ body.contentType=json
|
||||
→ body.content visible + required
|
||||
```
|
||||
|
||||
### Example 2: IF Node Operator Dependencies
|
||||
|
||||
**Scenario**: String comparison with different operators
|
||||
|
||||
**Binary operator** (equals):
|
||||
```javascript
|
||||
{
|
||||
"conditions": {
|
||||
"string": [
|
||||
{
|
||||
"operation": "equals"
|
||||
// → value1 required
|
||||
// → value2 required
|
||||
// → singleValue should NOT be set
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Unary operator** (isEmpty):
|
||||
```javascript
|
||||
{
|
||||
"conditions": {
|
||||
"string": [
|
||||
{
|
||||
"operation": "isEmpty"
|
||||
// → value1 required
|
||||
// → value2 should NOT be set
|
||||
// → singleValue should be true (auto-added)
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Dependency table**:
|
||||
|
||||
| Operator | value1 | value2 | singleValue |
|
||||
|---|---|---|---|
|
||||
| equals | Required | Required | false |
|
||||
| notEquals | Required | Required | false |
|
||||
| contains | Required | Required | false |
|
||||
| isEmpty | Required | Hidden | true |
|
||||
| isNotEmpty | Required | Hidden | true |
|
||||
|
||||
### Example 3: Slack Operation Matrix
|
||||
|
||||
**Scenario**: Different Slack operations show different fields
|
||||
|
||||
```javascript
|
||||
// post message
|
||||
{
|
||||
"resource": "message",
|
||||
"operation": "post"
|
||||
// Shows: channel (required), text (required), attachments, blocks
|
||||
}
|
||||
|
||||
// update message
|
||||
{
|
||||
"resource": "message",
|
||||
"operation": "update"
|
||||
// Shows: messageId (required), text (required), channel (optional)
|
||||
}
|
||||
|
||||
// delete message
|
||||
{
|
||||
"resource": "message",
|
||||
"operation": "delete"
|
||||
// Shows: messageId (required), channel (required)
|
||||
// Hides: text, attachments, blocks
|
||||
}
|
||||
|
||||
// get message
|
||||
{
|
||||
"resource": "message",
|
||||
"operation": "get"
|
||||
// Shows: messageId (required), channel (required)
|
||||
// Hides: text, attachments, blocks
|
||||
}
|
||||
```
|
||||
|
||||
**Field visibility matrix**:
|
||||
|
||||
| Field | post | update | delete | get |
|
||||
|---|---|---|---|---|
|
||||
| channel | Required | Optional | Required | Required |
|
||||
| text | Required | Required | Hidden | Hidden |
|
||||
| messageId | Hidden | Required | Required | Required |
|
||||
| attachments | Optional | Optional | Hidden | Hidden |
|
||||
| blocks | Optional | Optional | Hidden | Hidden |
|
||||
|
||||
---
|
||||
|
||||
## Nested Dependencies
|
||||
|
||||
### What Are They?
|
||||
|
||||
**Definition**: Dependencies within object properties
|
||||
|
||||
**Example**: HTTP Request body.contentType controls body.content structure
|
||||
|
||||
```javascript
|
||||
{
|
||||
"body": {
|
||||
"contentType": "json",
|
||||
// → content expects JSON object
|
||||
"content": {
|
||||
"key": "value"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"body": {
|
||||
"contentType": "form-data",
|
||||
// → content expects form fields array
|
||||
"content": [
|
||||
{
|
||||
"name": "field1",
|
||||
"value": "value1"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### How to Handle
|
||||
|
||||
**Strategy**: Configure parent first, then children
|
||||
|
||||
```javascript
|
||||
// Step 1: Parent
|
||||
{
|
||||
"body": {
|
||||
"contentType": "json" // Set parent first
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: Children (structure determined by parent)
|
||||
{
|
||||
"body": {
|
||||
"contentType": "json",
|
||||
"content": { // JSON object format
|
||||
"key": "value"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Auto-Sanitization and Dependencies
|
||||
|
||||
### What Auto-Sanitization Fixes
|
||||
|
||||
**Operator structure issues** (IF/Switch nodes):
|
||||
|
||||
**Example**: singleValue property
|
||||
```javascript
|
||||
// You configure (missing singleValue)
|
||||
{
|
||||
"type": "boolean",
|
||||
"operation": "isEmpty"
|
||||
// Missing singleValue
|
||||
}
|
||||
|
||||
// Auto-sanitization adds it
|
||||
{
|
||||
"type": "boolean",
|
||||
"operation": "isEmpty",
|
||||
"singleValue": true // ✅ Added automatically
|
||||
}
|
||||
```
|
||||
|
||||
### What It Doesn't Fix
|
||||
|
||||
**Missing required fields**:
|
||||
```javascript
|
||||
// You configure (missing channel)
|
||||
{
|
||||
"resource": "message",
|
||||
"operation": "post",
|
||||
"text": "Hello"
|
||||
// Missing required field: channel
|
||||
}
|
||||
|
||||
// Auto-sanitization does NOT add
|
||||
// You must add it yourself
|
||||
{
|
||||
"resource": "message",
|
||||
"operation": "post",
|
||||
"channel": "#general", // ← You must add
|
||||
"text": "Hello"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting Dependencies
|
||||
|
||||
### Problem 1: "Field X is required but not visible"
|
||||
|
||||
**Error**:
|
||||
```json
|
||||
{
|
||||
"type": "missing_required",
|
||||
"property": "body",
|
||||
"message": "body is required"
|
||||
}
|
||||
```
|
||||
|
||||
**But you don't see body field in configuration!**
|
||||
|
||||
**Solution**:
|
||||
```javascript
|
||||
// Check dependencies
|
||||
const deps = get_property_dependencies({
|
||||
nodeType: "nodes-base.httpRequest"
|
||||
});
|
||||
|
||||
// Find that body shows when sendBody=true
|
||||
// Add sendBody
|
||||
{
|
||||
"method": "POST",
|
||||
"sendBody": true, // ← Now body appears!
|
||||
"body": {...}
|
||||
}
|
||||
```
|
||||
|
||||
### Problem 2: "Field disappears when I change operation"
|
||||
|
||||
**Scenario**:
|
||||
```javascript
|
||||
// Working configuration
|
||||
{
|
||||
"resource": "message",
|
||||
"operation": "post",
|
||||
"channel": "#general",
|
||||
"text": "Hello"
|
||||
}
|
||||
|
||||
// Change operation
|
||||
{
|
||||
"resource": "message",
|
||||
"operation": "update", // Changed
|
||||
"channel": "#general", // Still here
|
||||
"text": "Updated" // Still here
|
||||
// Missing: messageId (required for update!)
|
||||
}
|
||||
```
|
||||
|
||||
**Validation error**: "messageId is required"
|
||||
|
||||
**Why**: Different operation = different required fields
|
||||
|
||||
**Solution**:
|
||||
```javascript
|
||||
// Check essentials for new operation
|
||||
get_node_essentials({
|
||||
nodeType: "nodes-base.slack"
|
||||
});
|
||||
|
||||
// Configure for update operation
|
||||
{
|
||||
"resource": "message",
|
||||
"operation": "update",
|
||||
"messageId": "1234567890", // Required for update
|
||||
"text": "Updated",
|
||||
"channel": "#general" // Optional for update
|
||||
}
|
||||
```
|
||||
|
||||
### Problem 3: "Validation passes but field doesn't save"
|
||||
|
||||
**Scenario**: Field hidden by dependencies after validation
|
||||
|
||||
**Example**:
|
||||
```javascript
|
||||
// Configure
|
||||
{
|
||||
"method": "GET",
|
||||
"sendBody": true, // ❌ GET doesn't support body
|
||||
"body": {...} // This will be stripped
|
||||
}
|
||||
|
||||
// After save
|
||||
{
|
||||
"method": "GET"
|
||||
// body removed because method=GET hides it
|
||||
}
|
||||
```
|
||||
|
||||
**Solution**: Respect dependencies from the start
|
||||
|
||||
```javascript
|
||||
// Correct approach
|
||||
get_property_dependencies({
|
||||
nodeType: "nodes-base.httpRequest"
|
||||
});
|
||||
|
||||
// See that body only shows for POST/PUT/PATCH/DELETE
|
||||
// Use correct method
|
||||
{
|
||||
"method": "POST",
|
||||
"sendBody": true,
|
||||
"body": {...}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Advanced Patterns
|
||||
|
||||
### Pattern 1: Conditional Required with Fallback
|
||||
|
||||
**Example**: Channel can be string OR expression
|
||||
|
||||
```javascript
|
||||
// Option 1: String
|
||||
{
|
||||
"channel": "#general"
|
||||
}
|
||||
|
||||
// Option 2: Expression
|
||||
{
|
||||
"channel": "={{$json.channelName}}"
|
||||
}
|
||||
|
||||
// Validation accepts both
|
||||
```
|
||||
|
||||
### Pattern 2: Mutually Exclusive Fields
|
||||
|
||||
**Example**: Use either ID or name, not both
|
||||
|
||||
```javascript
|
||||
// Use messageId
|
||||
{
|
||||
"messageId": "1234567890"
|
||||
// name not needed
|
||||
}
|
||||
|
||||
// OR use messageName
|
||||
{
|
||||
"messageName": "thread-name"
|
||||
// messageId not needed
|
||||
}
|
||||
|
||||
// Dependencies ensure only one is required
|
||||
```
|
||||
|
||||
### Pattern 3: Progressive Complexity
|
||||
|
||||
**Example**: Simple mode vs advanced mode
|
||||
|
||||
```javascript
|
||||
// Simple mode
|
||||
{
|
||||
"mode": "simple",
|
||||
"text": "{{$json.message}}"
|
||||
// Advanced fields hidden
|
||||
}
|
||||
|
||||
// Advanced mode
|
||||
{
|
||||
"mode": "advanced",
|
||||
"attachments": [...],
|
||||
"blocks": [...],
|
||||
"metadata": {...}
|
||||
// Simple field hidden, advanced fields shown
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
### ✅ Do
|
||||
|
||||
1. **Check dependencies when stuck**
|
||||
```javascript
|
||||
get_property_dependencies({nodeType: "..."});
|
||||
```
|
||||
|
||||
2. **Configure parent properties first**
|
||||
```javascript
|
||||
// First: method, resource, operation
|
||||
// Then: dependent fields
|
||||
```
|
||||
|
||||
3. **Validate after changing operation**
|
||||
```javascript
|
||||
// Operation changed → requirements changed
|
||||
validate_node_operation({...});
|
||||
```
|
||||
|
||||
4. **Read validation errors for dependency hints**
|
||||
```
|
||||
Error: "body required when sendBody=true"
|
||||
→ Hint: Set sendBody=true to enable body
|
||||
```
|
||||
|
||||
### ❌ Don't
|
||||
|
||||
1. **Don't ignore dependency errors**
|
||||
```javascript
|
||||
// Error: "body not visible" → Check displayOptions
|
||||
```
|
||||
|
||||
2. **Don't hardcode all possible fields**
|
||||
```javascript
|
||||
// Bad: Adding fields that will be hidden
|
||||
```
|
||||
|
||||
3. **Don't assume operations are identical**
|
||||
```javascript
|
||||
// Each operation has unique requirements
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
**Key Concepts**:
|
||||
- `displayOptions` control field visibility
|
||||
- `show` = field appears when conditions match
|
||||
- `hide` = field disappears when conditions match
|
||||
- Multiple conditions = AND logic
|
||||
- Multiple values = OR logic
|
||||
|
||||
**Common Patterns**:
|
||||
1. Boolean toggle (sendBody → body)
|
||||
2. Resource/operation cascade (different operations → different fields)
|
||||
3. Type-specific config (string vs boolean conditions)
|
||||
4. Method-specific fields (GET vs POST)
|
||||
|
||||
**Troubleshooting**:
|
||||
- Field required but not visible → Check dependencies
|
||||
- Field disappears after change → Operation changed requirements
|
||||
- Field doesn't save → Hidden by dependencies
|
||||
|
||||
**Tools**:
|
||||
- `get_property_dependencies` - See dependency rules
|
||||
- `get_node_essentials` - See operation requirements
|
||||
- Validation errors - Hints about dependencies
|
||||
|
||||
**Related Files**:
|
||||
- **[SKILL.md](SKILL.md)** - Main configuration guide
|
||||
- **[OPERATION_PATTERNS.md](OPERATION_PATTERNS.md)** - Common patterns by node type
|
||||
Reference in New Issue
Block a user