Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf681ef5

Browse files
author
Pankil Joshi
committed
Added wait and resume by webhook functionality
1 parent5176ae0 commitf681ef5

File tree

4 files changed

+336
-200
lines changed

4 files changed

+336
-200
lines changed

‎nodes/Lowcoder/AppDescription.ts

Lines changed: 53 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,12 @@
11
importtype{INodeProperties}from'n8n-workflow';
22

3-
exportconstappOperations:INodeProperties[]=[
4-
// ----------------------------------
5-
// app
6-
// ----------------------------------
7-
{
8-
displayName:'Operation',
9-
name:'operation',
10-
type:'options',
11-
noDataExpression:true,
12-
displayOptions:{
13-
show:{
14-
resource:['app'],
15-
},
16-
},
17-
options:[
18-
{
19-
name:'Create',
20-
value:'create',
21-
description:'Create a new app',
22-
action:'Create a app',
23-
},
24-
{
25-
name:'Delete',
26-
value:'delete',
27-
description:'Delete a app',
28-
action:'Delete a app',
29-
},
30-
{
31-
name:'Get',
32-
value:'get',
33-
description:'Get the data of a app',
34-
action:'Get a app',
35-
},
36-
{
37-
name:'Update',
38-
value:'update',
39-
description:'Update a app',
40-
action:'Update a app',
41-
},
42-
],
43-
default:'create',
44-
},
45-
];
46-
473
exportconstappFields:INodeProperties[]=[
484
// ----------------------------------
495
// app:create
506
// ----------------------------------
51-
{
52-
displayName:'Name',
53-
name:'name',
54-
type:'string',
55-
default:'',
56-
placeholder:'My app',
57-
required:true,
58-
displayOptions:{
59-
show:{
60-
operation:['create'],
61-
resource:['app'],
62-
},
63-
},
64-
description:'The name of the app',
65-
},
667
{
678
displayName:'App',
68-
name:'id',
9+
name:'appId',
6910
type:'resourceLocator',
7011
default:{mode:'list',value:''},
7112
required:true,
@@ -79,12 +20,6 @@ export const appFields: INodeProperties[] = [
7920
searchListMethod:'searchApps',
8021
},
8122
},
82-
{
83-
displayName:'By Name',
84-
name:'name',
85-
type:'string',
86-
placeholder:'name@example.tld\'s new app'
87-
},
8823
{
8924
displayName:'ID',
9025
name:'id',
@@ -101,12 +36,57 @@ export const appFields: INodeProperties[] = [
10136
placeholder:'65129e728953c27f7d15b64d',
10237
},
10338
],
104-
displayOptions:{
105-
show:{
106-
operation:['get','delete','update'],
107-
resource:['app'],
108-
},
109-
},
11039
description:'The ID of the app',
11140
}
112-
];
41+
];
42+
43+
exportconsthttpMethodsProperty:INodeProperties={
44+
displayName:'HTTP Method',
45+
name:'httpMethod',
46+
type:'options',
47+
options:[
48+
{
49+
name:'DELETE',
50+
value:'DELETE',
51+
},
52+
{
53+
name:'GET',
54+
value:'GET',
55+
},
56+
{
57+
name:'HEAD',
58+
value:'HEAD',
59+
},
60+
{
61+
name:'PATCH',
62+
value:'PATCH',
63+
},
64+
{
65+
name:'POST',
66+
value:'POST',
67+
},
68+
{
69+
name:'PUT',
70+
value:'PUT',
71+
},
72+
],
73+
default:'GET',
74+
description:'The HTTP method to listen to',
75+
};
76+
77+
exportconstoptionsProperty:INodeProperties={
78+
displayName:'Options',
79+
name:'options',
80+
type:'collection',
81+
placeholder:'Add Option',
82+
default:{},
83+
options:[
84+
{
85+
displayName:'Ignore Bots',
86+
name:'ignoreBots',
87+
type:'boolean',
88+
default:false,
89+
description:'Whether to ignore requests from bots like link previewers and web crawlers',
90+
}
91+
],
92+
};

‎nodes/Lowcoder/Lowcoder.node.ts

Lines changed: 75 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,29 @@
1-
import{
2-
IExecuteFunctions,
3-
}from'n8n-core';
1+
42

53
import{
6-
IDataObject,
7-
INodeExecutionData,
84
INodeType,
95
INodeTypeDescription,
106
ILoadOptionsFunctions,
117
INodeListSearchResult,
8+
IExecuteFunctions,
9+
INodeExecutionData,
10+
IWebhookFunctions,
11+
IWebhookResponseData,
12+
NodeApiError,
1213
}from'n8n-workflow';
1314

14-
import{
15-
OptionsWithUri,
16-
}from'request';
17-
import{appFields,appOperations}from'./AppDescription';
15+
import{appFields,httpMethodsProperty,optionsProperty}from'./AppDescription';
1816
import{apiRequest}from'./GenericFunctions';
17+
importisbotfrom'isbot';
1918

2019
interfaceLowcoderAppType{
2120
applicationId:string;
2221
name:string;
22+
applicationType:number
2323
}
2424

25+
constWAIT_TIME_UNLIMITED='3000-01-01T00:00:00.000Z';
26+
2527
exportclassLowcoderimplementsINodeType{
2628
description:INodeTypeDescription={
2729
displayName:'Lowcoder',
@@ -30,7 +32,7 @@ export class Lowcoder implements INodeType {
3032
icon:'file:lowcoder.png',
3133
group:['transform'],
3234
version:1,
33-
subtitle:'={{$parameter["operation"]+ ": " +$parameter["resource"] }}',
35+
subtitle:'={{$parameter["resource"]}}:{{$parameter["appId"]',
3436
description:'Consume Lowcoder API',
3537
defaults:{
3638
name:'Lowcoder',
@@ -42,7 +44,22 @@ export class Lowcoder implements INodeType {
4244
name:'lowcoderApi',
4345
required:true,
4446
},
45-
],
47+
],
48+
webhooks:[
49+
{
50+
name:'default',
51+
httpMethod:'={{$parameter["httpMethod"]}}',
52+
isFullPath:true,
53+
responseCode:'200',
54+
responseMode:'onReceived',
55+
responseData:'allEntries',
56+
responseContentType:'={{$parameter["options"]["responseContentType"]}}',
57+
responsePropertyName:'={{$parameter["options"]["responsePropertyName"]}}',
58+
responseHeaders:'={{$parameter["options"]["responseHeaders"]}}',
59+
path:'={{$parameter["appId"] || ""}}',
60+
restartWebhook:true,
61+
},
62+
],
4663
properties:[
4764
{
4865
displayName:'Resource',
@@ -57,8 +74,16 @@ export class Lowcoder implements INodeType {
5774
],
5875
default:'app',
5976
},
60-
...appOperations,
61-
...appFields
77+
...appFields,
78+
{
79+
displayName:
80+
'The webhook URL will be generated at run time. It can be referenced with the <strong>$execution.resumeUrl</strong> variable. Send it somewhere before getting to this node. <a href="https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.wait/?utm_source=n8n_app&utm_medium=node_settings_modal-credential_link&utm_campaign=n8n-nodes-base.wait" target="_blank">More info</a>',
81+
name:'webhookNotice',
82+
type:'notice',
83+
default:'',
84+
},
85+
httpMethodsProperty,
86+
optionsProperty
6287
],
6388
};
6489

@@ -79,60 +104,55 @@ export class Lowcoder implements INodeType {
79104
withContainerSize:false
80105
},
81106
);
82-
console.log(searchResults);
83107

84108
return{
85109
results:searchResults.data.map((b:LowcoderAppType)=>({
86-
name:b.name,
110+
name:`${b.name} (${b.applicationType==2 ?"Module" :"App"})`,
87111
value:b.applicationId,
88112
})),
89113
};
90114
},
91115
},
92116
};
93117

94-
// The execute method will go here
95-
asyncexecute(this:IExecuteFunctions):Promise<INodeExecutionData[][]>{
96-
constitems=this.getInputData();
97-
letresponseData;
98-
constreturnData=[];
99-
constresource=this.getNodeParameter('resource',0)asstring;
100-
constoperation=this.getNodeParameter('operation',0)asstring;
118+
asyncwebhook(this:IWebhookFunctions):Promise<IWebhookResponseData>{
119+
constoptions=this.getNodeParameter('options',{})as{
120+
binaryData:boolean;
121+
ignoreBots:boolean;
122+
rawBody:Buffer;
123+
responseData?:string;
124+
};
125+
constreq=this.getRequestObject();
126+
constresp=this.getResponseObject();
127+
128+
try{
129+
if(options.ignoreBots&&isbot(req.headers['user-agent'])){
130+
thrownewNodeApiError(this.getNode(),{},{message:'Authorization data is wrong!'});
131+
}
132+
}catch(error){
133+
resp.writeHead(error.responseCode,{'WWW-Authenticate':'Basic realm="Webhook"'});
134+
resp.end(error.message);
135+
return{noWebhookResponse:true};
136+
}
137+
// const { data } = req.body;
138+
139+
constreturnItem:INodeExecutionData={
140+
binary:{},
141+
json:{
142+
headers:req.headers,
143+
params:req.params,
144+
query:req.query,
145+
// body: data,
146+
},
147+
};
148+
return{workflowData:[[returnItem]]};
149+
}
101150

102-
// For each item, make an API call to create a contact
103-
for(leti=0;i<items.length;i++){
104-
if(resource==='app'){
105-
if(operation==='create'){
106-
// Get email input
107-
constemail=this.getNodeParameter('email',i)asstring;
108-
// Get additional fields input
109-
constadditionalFields=this.getNodeParameter('additionalFields',i)asIDataObject;
110-
constdata:IDataObject={
111-
email,
112-
};
151+
asyncexecute(this:IExecuteFunctions):Promise<INodeExecutionData[][]>{
113152

114-
Object.assign(data,additionalFields);
153+
letwaitTill=newDate(WAIT_TIME_UNLIMITED);
115154

116-
// Make HTTP request according to https://sendgrid.com/docs/api-reference/
117-
constoptions:OptionsWithUri={
118-
headers:{
119-
'Accept':'application/json',
120-
},
121-
method:'PUT',
122-
body:{
123-
contacts:[
124-
data,
125-
],
126-
},
127-
uri:`https://api.sendgrid.com/v3/marketing/contacts`,
128-
json:true,
129-
};
130-
responseData=awaitthis.helpers.requestWithAuthentication.call(this,'friendGridApi',options);
131-
returnData.push(responseData);
132-
}
133-
}
134-
}
135-
// Map data to n8n data structure
136-
return[this.helpers.returnJsonArray(returnData)];
155+
awaitthis.putExecutionToWait(waitTill);
156+
return[this.getInputData()];
137157
}
138158
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp