1
-
2
-
3
1
import {
4
- INodeType ,
5
- INodeTypeDescription ,
2
+ INodeType ,
3
+ INodeTypeDescription ,
6
4
ILoadOptionsFunctions ,
7
5
INodeListSearchResult ,
8
6
IExecuteFunctions ,
@@ -17,22 +15,22 @@ import { apiRequest } from './GenericFunctions';
17
15
import isbot from 'isbot' ;
18
16
19
17
interface LowcoderAppType {
20
- applicationId : string ;
21
- name : string ;
18
+ applicationId : string ;
19
+ name : string ;
22
20
applicationType : number
23
21
}
24
22
25
23
const WAIT_TIME_UNLIMITED = '3000-01-01T00:00:00.000Z' ;
26
24
27
25
export class Lowcoder implements INodeType {
28
- description : INodeTypeDescription = {
26
+ description : INodeTypeDescription = {
29
27
displayName : 'Lowcoder' ,
30
28
name : 'lowcoder' ,
31
29
// eslint-disable-next-line n8n-nodes-base/node-class-description-icon-not-svg
32
30
icon : 'file:lowcoder.png' ,
33
31
group : [ 'transform' ] ,
34
32
version : 1 ,
35
- subtitle : '=app:{{ $parameter["appId"]' ,
33
+ subtitle : '=app:{{ $parameter["appId"]' ,
36
34
description : 'Consume Lowcoder API' ,
37
35
defaults : {
38
36
name : 'Lowcoder' ,
@@ -50,100 +48,121 @@ export class Lowcoder implements INodeType {
50
48
name : 'default' ,
51
49
httpMethod : '={{$parameter["httpMethod"]}}' ,
52
50
isFullPath : true ,
53
- responseCode : '200' ,
54
51
responseMode : 'onReceived' ,
55
- responseData : 'allEntries ' ,
56
- responseContentType : '={{$parameter["options"]["responseContentType"]}}' ,
52
+ responseData : '={{$parameter["options"]["responseData"] || "Workflow Resumed!"}} ' ,
53
+ responseContentType : '={{$parameter["options"]["responseContentType"] || "application/json" }}' ,
57
54
responsePropertyName : '={{$parameter["options"]["responsePropertyName"]}}' ,
58
55
responseHeaders : '={{$parameter["options"]["responseHeaders"]}}' ,
59
56
path : '={{$parameter["appId"] || ""}}' ,
60
- restartWebhook : true ,
57
+ restartWebhook : true ,
61
58
} ,
62
- ] ,
59
+ ] ,
63
60
properties : [
64
61
...appFields ,
65
62
{
66
- displayName : 'Resume the workflow by calling this Webhook: http(s)://{n8n-url}/webhook-waiting/{Workflow-Execution-ID}/{Lowcoder-App-ID}' ,
67
- name : 'webhookNotice' ,
68
- type : 'notice' ,
69
- default : '' ,
70
- } ,
71
- {
72
- displayName : 'The Workflow-Execution-ID is available via the n8n Rest API' ,
73
- name : 'webhookNotice' ,
74
- type : 'notice' ,
75
- default : '' ,
76
- } ,
63
+ displayName : 'Resume the workflow by calling this Webhook: http(s)://{n8n-url}/webhook-waiting/{Workflow-Execution-ID}/{Lowcoder-App-ID}' ,
64
+ name : 'webhookNotice' ,
65
+ type : 'notice' ,
66
+ default : '' ,
67
+ } ,
68
+ {
69
+ displayName : 'The Workflow-Execution-ID is available via the n8n Rest API' ,
70
+ name : 'webhookNotice' ,
71
+ type : 'notice' ,
72
+ default : '' ,
73
+ } ,
77
74
httpMethodsProperty ,
78
- optionsProperty
75
+ optionsProperty ,
76
+ {
77
+ displayName : 'Response Code' ,
78
+ name : 'responseCode' ,
79
+ type : 'number' ,
80
+ default : 200 ,
81
+ description : 'The HTTP response code to return' ,
82
+ } ,
79
83
] ,
80
- } ;
84
+ } ;
81
85
82
86
methods = {
83
- listSearch : {
84
- async searchApps (
85
- this : ILoadOptionsFunctions ,
86
- query ?: string ,
87
- ) : Promise < INodeListSearchResult > {
88
-
89
- const searchResults = await apiRequest . call (
90
- this ,
91
- 'GET' ,
92
- 'applications/list' ,
93
- { } ,
94
- {
95
- query,
87
+ listSearch : {
88
+ async searchApps (
89
+ this : ILoadOptionsFunctions ,
90
+ query ?: string ,
91
+ ) : Promise < INodeListSearchResult > {
92
+ const searchResults = await apiRequest . call (
93
+ this ,
94
+ 'GET' ,
95
+ 'applications/list' ,
96
+ { } ,
97
+ {
98
+ query,
96
99
withContainerSize : false
97
- } ,
98
- ) ;
99
- console . log ( searchResults ) ;
100
- return {
101
- results : searchResults . data . map ( ( b : LowcoderAppType ) => ( {
102
- name : `${ b . name } (${ b . applicationType == 2 ? "Module" : "App" } )` ,
103
- value : b . applicationId ,
104
- } ) ) ,
105
- } ;
106
- } ,
107
- } ,
108
- } ;
100
+ } ,
101
+ ) ;
102
+ console . log ( searchResults ) ;
103
+ return {
104
+ results : searchResults . data . map ( ( b : LowcoderAppType ) => ( {
105
+ name : `${ b . name } (${ b . applicationType == 2 ? "Module" : "App" } )` ,
106
+ value : b . applicationId ,
107
+ } ) ) ,
108
+ } ;
109
+ } ,
110
+ } ,
111
+ } ;
109
112
110
113
async webhook ( this : IWebhookFunctions ) : Promise < IWebhookResponseData > {
111
- const options = this . getNodeParameter ( 'options' , { } ) as {
112
- binaryData : boolean ;
113
- ignoreBots : boolean ;
114
- rawBody : Buffer ;
115
- responseData ?: string ;
116
- } ;
117
- const req = this . getRequestObject ( ) ;
118
- const resp = this . getResponseObject ( ) ;
114
+ const options = this . getNodeParameter ( 'options' , { } ) as {
115
+ binaryData : boolean ;
116
+ ignoreBots : boolean ;
117
+ rawBody : Buffer ;
118
+ responseData ?: string ;
119
+ responseCode ?: number ;
120
+ } ;
121
+ const req = this . getRequestObject ( ) ;
122
+ const resp = this . getResponseObject ( ) ;
119
123
120
- try {
121
- if ( options . ignoreBots && isbot ( req . headers [ 'user-agent' ] ) ) {
122
- throw new NodeApiError ( this . getNode ( ) , { } , { message : 'Authorization data is wrong!' } ) ;
124
+ try {
125
+ if ( options . ignoreBots && isbot ( req . headers [ 'user-agent' ] ) ) {
126
+ throw new NodeApiError ( this . getNode ( ) , { } , { message : 'Authorization data is wrong!' } ) ;
123
127
}
124
- } catch ( error ) {
125
- resp . writeHead ( error . responseCode , { 'WWW-Authenticate' : 'Basic realm="Webhook"' } ) ;
128
+ } catch ( error ) {
129
+ resp . writeHead ( error . responseCode || 401 , { 'WWW-Authenticate' : 'Basic realm="Webhook"' } ) ;
126
130
resp . end ( error . message ) ;
127
131
return { noWebhookResponse : true } ;
128
- }
129
- const body = typeof req . body != 'undefined' ? req . body : { } ;
130
- const returnItem : INodeExecutionData = {
131
- binary : { } ,
132
- json : {
133
- headers : req . headers ,
134
- params : req . params ,
135
- query : req . query ,
136
- body : body ,
137
- } ,
138
- } ;
139
- return { workflowData : [ [ returnItem ] ] } ;
140
- }
132
+ }
141
133
142
- async execute ( this : IExecuteFunctions ) : Promise < INodeExecutionData [ ] [ ] > {
134
+ const type = req . query . type ;
135
+ if ( type === 'resume' ) {
136
+ // Resume workflow as before
137
+ const body = typeof req . body != 'undefined' ? req . body : { } ;
138
+ const returnItem : INodeExecutionData = {
139
+ binary : { } ,
140
+ json : {
141
+ headers : req . headers ,
142
+ params : req . params ,
143
+ query : req . query ,
144
+ body : body ,
145
+ } ,
146
+ } ;
147
+ const responseCode = options . responseCode || 200 ;
148
+ resp . statusCode = responseCode ;
149
+ return { workflowData : [ [ returnItem ] ] } ;
150
+ } else {
151
+ // Return input data, and don't resume
152
+ const staticData = this . getWorkflowStaticData ( 'node' ) ;
153
+ const previousData = staticData . previousNodeData || [ ] ;
154
+ resp . statusCode = 200 ;
155
+ resp . setHeader ( 'Content-Type' , 'application/json' ) ;
156
+ resp . end ( JSON . stringify ( { message : 'Static response: workflow not resumed' , type, previousData } ) ) ;
157
+ return { noWebhookResponse : true } ;
158
+ }
159
+ }
143
160
161
+ async execute ( this : IExecuteFunctions ) : Promise < INodeExecutionData [ ] [ ] > {
144
162
let waitTill = new Date ( WAIT_TIME_UNLIMITED ) ;
145
-
163
+ const staticData = this . getWorkflowStaticData ( 'node' ) ;
164
+ staticData . previousNodeData = this . getInputData ( ) . map ( item => item . json ) ;
146
165
await this . putExecutionToWait ( waitTill ) ;
147
- return [ this . getInputData ( ) ] ;
148
- }
166
+ return [ this . getInputData ( ) ] ;
167
+ }
149
168
}
0 commit comments