1
- import {
2
- IExecuteFunctions ,
3
- } from 'n8n-core' ;
1
+
4
2
5
3
import {
6
- IDataObject ,
7
- INodeExecutionData ,
8
4
INodeType ,
9
5
INodeTypeDescription ,
10
6
ILoadOptionsFunctions ,
11
7
INodeListSearchResult ,
8
+ IExecuteFunctions ,
9
+ INodeExecutionData ,
10
+ IWebhookFunctions ,
11
+ IWebhookResponseData ,
12
+ NodeApiError ,
12
13
} from 'n8n-workflow' ;
13
14
14
- import {
15
- OptionsWithUri ,
16
- } from 'request' ;
17
- import { appFields , appOperations } from './AppDescription' ;
15
+ import { appFields , httpMethodsProperty , optionsProperty } from './AppDescription' ;
18
16
import { apiRequest } from './GenericFunctions' ;
17
+ import isbot from 'isbot' ;
19
18
20
19
interface LowcoderAppType {
21
20
applicationId : string ;
22
21
name : string ;
22
+ applicationType : number
23
23
}
24
24
25
+ const WAIT_TIME_UNLIMITED = '3000-01-01T00:00:00.000Z' ;
26
+
25
27
export class Lowcoder implements INodeType {
26
28
description : INodeTypeDescription = {
27
29
displayName : 'Lowcoder' ,
@@ -30,7 +32,7 @@ export class Lowcoder implements INodeType {
30
32
icon : 'file:lowcoder.png' ,
31
33
group : [ 'transform' ] ,
32
34
version : 1 ,
33
- subtitle : '={{ $parameter["operation "] + ": " + $parameter["resource"] }} ' ,
35
+ subtitle : '={{$parameter["resource "] }}:{{ $parameter["appId"] ' ,
34
36
description : 'Consume Lowcoder API' ,
35
37
defaults : {
36
38
name : 'Lowcoder' ,
@@ -42,7 +44,22 @@ export class Lowcoder implements INodeType {
42
44
name : 'lowcoderApi' ,
43
45
required : true ,
44
46
} ,
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
+ ] ,
46
63
properties : [
47
64
{
48
65
displayName : 'Resource' ,
@@ -57,8 +74,16 @@ export class Lowcoder implements INodeType {
57
74
] ,
58
75
default : 'app' ,
59
76
} ,
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
62
87
] ,
63
88
} ;
64
89
@@ -79,60 +104,55 @@ export class Lowcoder implements INodeType {
79
104
withContainerSize : false
80
105
} ,
81
106
) ;
82
- console . log ( searchResults ) ;
83
107
84
108
return {
85
109
results : searchResults . data . map ( ( b : LowcoderAppType ) => ( {
86
- name : b . name ,
110
+ name : ` ${ b . name } ( ${ b . applicationType == 2 ? "Module" : "App" } )` ,
87
111
value : b . applicationId ,
88
112
} ) ) ,
89
113
} ;
90
114
} ,
91
115
} ,
92
116
} ;
93
117
94
- // The execute method will go here
95
- async execute ( this : IExecuteFunctions ) : Promise < INodeExecutionData [ ] [ ] > {
96
- const items = this . getInputData ( ) ;
97
- let responseData ;
98
- const returnData = [ ] ;
99
- const resource = this . getNodeParameter ( 'resource' , 0 ) as string ;
100
- const operation = this . getNodeParameter ( 'operation' , 0 ) as string ;
118
+ async webhook ( this : IWebhookFunctions ) : Promise < IWebhookResponseData > {
119
+ const options = this . getNodeParameter ( 'options' , { } ) as {
120
+ binaryData : boolean ;
121
+ ignoreBots : boolean ;
122
+ rawBody : Buffer ;
123
+ responseData ?: string ;
124
+ } ;
125
+ const req = this . getRequestObject ( ) ;
126
+ const resp = this . getResponseObject ( ) ;
127
+
128
+ try {
129
+ if ( options . ignoreBots && isbot ( req . headers [ 'user-agent' ] ) ) {
130
+ throw new NodeApiError ( 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
+ const returnItem : 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
+ }
101
150
102
- // For each item, make an API call to create a contact
103
- for ( let i = 0 ; i < items . length ; i ++ ) {
104
- if ( resource === 'app' ) {
105
- if ( operation === 'create' ) {
106
- // Get email input
107
- const email = this . getNodeParameter ( 'email' , i ) as string ;
108
- // Get additional fields input
109
- const additionalFields = this . getNodeParameter ( 'additionalFields' , i ) as IDataObject ;
110
- const data : IDataObject = {
111
- email,
112
- } ;
151
+ async execute ( this : IExecuteFunctions ) : Promise < INodeExecutionData [ ] [ ] > {
113
152
114
- Object . assign ( data , additionalFields ) ;
153
+ let waitTill = new Date ( WAIT_TIME_UNLIMITED ) ;
115
154
116
- // Make HTTP request according to https://sendgrid.com/docs/api-reference/
117
- const options : 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 = await this . 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
+ await this . putExecutionToWait ( waitTill ) ;
156
+ return [ this . getInputData ( ) ] ;
137
157
}
138
158
}
0 commit comments