Skip to content

Commit eb30006

Browse files
feat: add create workflow execution functionality with parameters and… (#1)
* feat: add create workflow execution functionality with parameters and API integration * feat: update Feather node options and enhance create workflow execution to conditionally include forwardingPhoneNumber * fix: update TypeScript version specification and format JSON files for consistency * fix: change default value of forwardingPhoneNumber parameter to null for better handling of optional input
1 parent 67474ce commit eb30006

File tree

5 files changed

+292
-23
lines changed

5 files changed

+292
-23
lines changed

nodes/Feather/Feather.node.ts

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import { executeCancelWorkflowExecution } from './operations/cancelWorkflowExecu
1010
import { cancelWorkflowExecutionDescription } from './operations/cancelWorkflowExecution.description';
1111
import { executeCreateAgentWorkflow } from './operations/createAgentWorkflow';
1212
import { createAgentWorkflowDescription } from './operations/createAgentWorkflow.description';
13+
import { executeCreateWorkflowExecution } from './operations/createWorkflowExecution';
14+
import { createWorkflowExecutionDescription } from './operations/createWorkflowExecution.description';
1315
import { executeDispatchPhoneCall } from './operations/dispatchPhoneCall';
1416
import { dispatchPhoneCallDescription } from './operations/dispatchPhoneCall.description';
1517
import { executeGetWorkflows } from './operations/getWorkflows';
@@ -43,16 +45,10 @@ export class Feather implements INodeType {
4345
noDataExpression: true,
4446
options: [
4547
{
46-
name: 'Get Workflows',
47-
value: 'getWorkflows',
48-
description: 'Get a list of workflows',
49-
action: 'Get workflows',
50-
},
51-
{
52-
name: 'Dispatch Phone Call',
53-
value: 'dispatchPhoneCall',
54-
description: 'Dispatch a phone call with custom parameters',
55-
action: 'Dispatch a phone call',
48+
name: 'Cancel Workflow Execution',
49+
value: 'cancelWorkflowExecution',
50+
description: 'Cancel a workflow execution',
51+
action: 'Cancel a workflow execution',
5652
},
5753
{
5854
name: 'Create Agent Workflow',
@@ -61,17 +57,30 @@ export class Feather implements INodeType {
6157
action: 'Create an agent workflow',
6258
},
6359
{
64-
name: 'Cancel Workflow Execution',
65-
value: 'cancelWorkflowExecution',
66-
description: 'Cancel a workflow execution',
67-
action: 'Cancel a workflow execution',
60+
name: 'Create Workflow Execution',
61+
value: 'createWorkflowExecution',
62+
description: 'Create a new workflow execution',
63+
action: 'Create a workflow execution',
64+
},
65+
{
66+
name: 'Dispatch Phone Call',
67+
value: 'dispatchPhoneCall',
68+
description: 'Dispatch a phone call with custom parameters',
69+
action: 'Dispatch a phone call',
70+
},
71+
{
72+
name: 'Get Workflows',
73+
value: 'getWorkflows',
74+
description: 'Get a list of workflows',
75+
action: 'Get workflows',
6876
},
6977
],
7078
default: 'getWorkflows',
7179
},
7280
...getWorkflowsDescription,
7381
...dispatchPhoneCallDescription,
7482
...createAgentWorkflowDescription,
83+
...createWorkflowExecutionDescription,
7584
...cancelWorkflowExecutionDescription,
7685
],
7786
};
@@ -96,6 +105,8 @@ export class Feather implements INodeType {
96105
returnData.push(await executeDispatchPhoneCall.call(this, i, baseURL, credentials));
97106
} else if (operation === 'createAgentWorkflow') {
98107
returnData.push(await executeCreateAgentWorkflow.call(this, i, baseURL));
108+
} else if (operation === 'createWorkflowExecution') {
109+
returnData.push(await executeCreateWorkflowExecution.call(this, i, baseURL));
99110
} else if (operation === 'cancelWorkflowExecution') {
100111
returnData.push(await executeCancelWorkflowExecution.call(this, i, baseURL));
101112
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import { INodeProperties } from 'n8n-workflow';
2+
3+
export const createWorkflowExecutionDescription: INodeProperties[] = [
4+
{
5+
displayName: 'Workflow ID',
6+
name: 'workflowId',
7+
type: 'string',
8+
required: true,
9+
default: '',
10+
displayOptions: {
11+
show: {
12+
operation: ['createWorkflowExecution'],
13+
},
14+
},
15+
description: 'The ID of the workflow to execute',
16+
},
17+
{
18+
displayName: 'Customer Lead ID',
19+
name: 'customerLeadId',
20+
type: 'string',
21+
required: true,
22+
default: '',
23+
displayOptions: {
24+
show: {
25+
operation: ['createWorkflowExecution'],
26+
},
27+
},
28+
description: 'Customer lead identifier',
29+
},
30+
{
31+
displayName: 'Primary Phone',
32+
name: 'primaryPhone',
33+
type: 'string',
34+
required: true,
35+
default: '',
36+
displayOptions: {
37+
show: {
38+
operation: ['createWorkflowExecution'],
39+
},
40+
},
41+
description: 'Primary phone number for the execution',
42+
},
43+
{
44+
displayName: 'Zipcode',
45+
name: 'zipcode',
46+
type: 'string',
47+
default: '',
48+
displayOptions: {
49+
show: {
50+
operation: ['createWorkflowExecution'],
51+
},
52+
},
53+
description: 'Zipcode for the execution',
54+
},
55+
{
56+
displayName: 'State',
57+
name: 'state',
58+
type: 'string',
59+
default: '',
60+
displayOptions: {
61+
show: {
62+
operation: ['createWorkflowExecution'],
63+
},
64+
},
65+
description: 'State for the execution',
66+
},
67+
{
68+
displayName: 'Forwarding Phone Number',
69+
name: 'forwardingPhoneNumber',
70+
type: 'string',
71+
default: '',
72+
displayOptions: {
73+
show: {
74+
operation: ['createWorkflowExecution'],
75+
},
76+
},
77+
description: 'Phone number to forward calls to',
78+
},
79+
{
80+
displayName: 'Additional Fields',
81+
name: 'additionalFields',
82+
type: 'collection',
83+
placeholder: 'Add Field',
84+
default: {},
85+
displayOptions: {
86+
show: {
87+
operation: ['createWorkflowExecution'],
88+
},
89+
},
90+
options: [
91+
{
92+
displayName: 'First Name',
93+
name: 'firstName',
94+
type: 'string',
95+
default: '',
96+
description: 'First name for metadata',
97+
},
98+
{
99+
displayName: 'Last Name',
100+
name: 'lastName',
101+
type: 'string',
102+
default: '',
103+
description: 'Last name for metadata',
104+
},
105+
{
106+
displayName: 'Variables (JSON)',
107+
name: 'variables',
108+
type: 'json',
109+
default: '{}',
110+
description: 'Variables for the execution as JSON object',
111+
},
112+
{
113+
displayName: 'Additional Metadata (JSON)',
114+
name: 'additionalMetadata',
115+
type: 'json',
116+
default: '{}',
117+
description: 'Additional metadata fields as JSON object',
118+
},
119+
],
120+
},
121+
];
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import { IExecuteFunctions, INodeExecutionData, NodeOperationError } from 'n8n-workflow';
2+
3+
export async function executeCreateWorkflowExecution(
4+
this: IExecuteFunctions,
5+
i: number,
6+
baseURL: string,
7+
): Promise<INodeExecutionData> {
8+
try {
9+
console.log('Starting workflow execution creation...');
10+
11+
// Get required parameters
12+
const workflowId = this.getNodeParameter('workflowId', i) as string;
13+
const customerLeadId = this.getNodeParameter('customerLeadId', i) as string;
14+
const primaryPhone = this.getNodeParameter('primaryPhone', i) as string;
15+
16+
// Get optional parameters
17+
const zipcode = this.getNodeParameter('zipcode', i, null) as string | null;
18+
const state = this.getNodeParameter('state', i, null) as string | null;
19+
const forwardingPhoneNumber = this.getNodeParameter('forwardingPhoneNumber', i, null) as
20+
| string
21+
| null;
22+
23+
// Get additional fields
24+
const additionalFields = this.getNodeParameter('additionalFields', i, {}) as Record<
25+
string,
26+
unknown
27+
>;
28+
29+
console.log('Basic parameters:', { workflowId, customerLeadId, primaryPhone, zipcode, state });
30+
31+
// Build request body
32+
const body: Record<string, unknown> = {
33+
customerLeadId,
34+
primaryPhone,
35+
zipcode,
36+
state,
37+
};
38+
39+
// Only include forwardingPhoneNumber if it's provided
40+
if (forwardingPhoneNumber) {
41+
body.forwardingPhoneNumber = forwardingPhoneNumber;
42+
}
43+
44+
// Handle variables (JSON)
45+
if (additionalFields.variables) {
46+
try {
47+
body.variables =
48+
typeof additionalFields.variables === 'string'
49+
? JSON.parse(additionalFields.variables as string)
50+
: additionalFields.variables;
51+
} catch {
52+
throw new NodeOperationError(this.getNode(), 'Invalid JSON in Variables field', {
53+
itemIndex: i,
54+
});
55+
}
56+
} else {
57+
body.variables = {};
58+
}
59+
60+
// Handle metadata
61+
const metadata: Record<string, unknown> = {};
62+
if (additionalFields.firstName) {
63+
metadata.firstName = additionalFields.firstName;
64+
}
65+
if (additionalFields.lastName) {
66+
metadata.lastName = additionalFields.lastName;
67+
}
68+
69+
// Add any additional metadata fields
70+
if (additionalFields.additionalMetadata) {
71+
try {
72+
const additionalMetadata =
73+
typeof additionalFields.additionalMetadata === 'string'
74+
? JSON.parse(additionalFields.additionalMetadata as string)
75+
: additionalFields.additionalMetadata;
76+
Object.assign(metadata, additionalMetadata);
77+
} catch {
78+
throw new NodeOperationError(this.getNode(), 'Invalid JSON in Additional Metadata field', {
79+
itemIndex: i,
80+
});
81+
}
82+
}
83+
84+
body.metadata = metadata;
85+
86+
console.log('Preparing API request with execution data:', JSON.stringify(body, null, 2));
87+
88+
try {
89+
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'featherApi', {
90+
method: 'POST',
91+
url: `${baseURL}/api/v1/workflow/${workflowId}/execution`,
92+
headers: {
93+
'Content-Type': 'application/json',
94+
accept: 'application/json, text/plain, */*',
95+
},
96+
body,
97+
json: true,
98+
});
99+
100+
console.log('Workflow execution created successfully:', JSON.stringify(response, null, 2));
101+
102+
return {
103+
json: response,
104+
pairedItem: {
105+
item: i,
106+
},
107+
};
108+
} catch (apiError) {
109+
console.error('API request failed:', apiError);
110+
console.error('Request details:', {
111+
url: `${baseURL}/api/v1/workflow/${workflowId}/execution`,
112+
workflowId,
113+
body,
114+
});
115+
throw apiError;
116+
}
117+
} catch (error) {
118+
console.error('Error in workflow execution creation:', error);
119+
throw error;
120+
}
121+
}

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,17 @@
44
"description": "n8n community node to work with the Example API",
55
"license": "MIT",
66
"homepage": "https://example.com",
7-
"keywords": ["n8n-community-node-package"],
8-
"author": { "name": "radioactive11", "email": "roy.arijit@icloud.com" },
9-
"repository": { "type": "git", "url": "" },
7+
"keywords": [
8+
"n8n-community-node-package"
9+
],
10+
"author": {
11+
"name": "radioactive11",
12+
"email": "roy.arijit@icloud.com"
13+
},
14+
"repository": {
15+
"type": "git",
16+
"url": ""
17+
},
1018
"scripts": {
1119
"build": "n8n-node build",
1220
"build:watch": "tsc --watch",
@@ -16,18 +24,26 @@
1624
"release": "n8n-node release",
1725
"prepublishOnly": "n8n-node prerelease"
1826
},
19-
"files": ["dist"],
27+
"files": [
28+
"dist"
29+
],
2030
"n8n": {
2131
"n8nNodesApiVersion": 1,
22-
"credentials": ["dist/credentials/FeatherApi.credentials.js"],
23-
"nodes": ["dist/nodes/Feather/Feather.node.js"]
32+
"credentials": [
33+
"dist/credentials/FeatherApi.credentials.js"
34+
],
35+
"nodes": [
36+
"dist/nodes/Feather/Feather.node.js"
37+
]
2438
},
2539
"devDependencies": {
2640
"@n8n/node-cli": "0.11.0",
2741
"eslint": "9.32.0",
2842
"prettier": "3.6.2",
2943
"release-it": "^19.0.4",
30-
"typescript": "5.9.2"
44+
"typescript": "^5.9.2"
3145
},
32-
"peerDependencies": { "n8n-workflow": "*" }
46+
"peerDependencies": {
47+
"n8n-workflow": "*"
48+
}
3349
}

0 commit comments

Comments
 (0)