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

Commit f7ea193

Browse files
committed
update: add type param to webhook
1 parent 06d2d7e commit f7ea193

File tree

1 file changed

+100
-81
lines changed

1 file changed

+100
-81
lines changed

‎nodes/Lowcoder/Lowcoder.node.ts

Lines changed: 100 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
2-
31
import {
4-
INodeType,
5-
INodeTypeDescription,
2+
INodeType,
3+
INodeTypeDescription,
64
ILoadOptionsFunctions,
75
INodeListSearchResult,
86
IExecuteFunctions,
@@ -17,22 +15,22 @@ import { apiRequest } from './GenericFunctions';
1715
import isbot from 'isbot';
1816

1917
interface LowcoderAppType {
20-
applicationId: string;
21-
name: string;
18+
applicationId: string;
19+
name: string;
2220
applicationType: number
2321
}
2422

2523
const WAIT_TIME_UNLIMITED = '3000年01月01日T00:00:00.000Z';
2624

2725
export class Lowcoder implements INodeType {
28-
description: INodeTypeDescription = {
26+
description: INodeTypeDescription = {
2927
displayName: 'Lowcoder',
3028
name: 'lowcoder',
3129
// eslint-disable-next-line n8n-nodes-base/node-class-description-icon-not-svg
3230
icon: 'file:lowcoder.png',
3331
group: ['transform'],
3432
version: 1,
35-
subtitle: '=app:{{ $parameter["appId"]',
33+
subtitle: '=app:{{ $parameter["appId"]',
3634
description: 'Consume Lowcoder API',
3735
defaults: {
3836
name: 'Lowcoder',
@@ -50,100 +48,121 @@ export class Lowcoder implements INodeType {
5048
name: 'default',
5149
httpMethod: '={{$parameter["httpMethod"]}}',
5250
isFullPath: true,
53-
responseCode: '200',
5451
responseMode: 'onReceived',
55-
responseData: 'allEntries',
56-
responseContentType: '={{$parameter["options"]["responseContentType"]}}',
52+
responseData: '={{$parameter["options"]["responseData"] || "Workflow Resumed!"}}',
53+
responseContentType: '={{$parameter["options"]["responseContentType"] || "application/json"}}',
5754
responsePropertyName: '={{$parameter["options"]["responsePropertyName"]}}',
5855
responseHeaders: '={{$parameter["options"]["responseHeaders"]}}',
5956
path: '={{$parameter["appId"] || ""}}',
60-
restartWebhook: true,
57+
restartWebhook: true,
6158
},
62-
],
59+
],
6360
properties: [
6461
...appFields,
6562
{
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+
},
7774
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+
},
7983
],
80-
};
84+
};
8185

8286
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,
9699
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+
};
109112

110113
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();
119123

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!' });
123127
}
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"' });
126130
resp.end(error.message);
127131
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+
}
141133

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+
}
143160

161+
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
144162
let waitTill = new Date(WAIT_TIME_UNLIMITED);
145-
163+
const staticData = this.getWorkflowStaticData('node');
164+
staticData.previousNodeData = this.getInputData().map(item => item.json);
146165
await this.putExecutionToWait(waitTill);
147-
return [this.getInputData()];
148-
}
166+
return [this.getInputData()];
167+
}
149168
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /