@guayaba/workflow-piece-webhook 0.1.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,28 @@
1
+ {
2
+ "Webhook": "Webhook",
3
+ "Receive HTTP requests and trigger flows using unique URLs.": "Receive HTTP requests and trigger flows using unique URLs.",
4
+ "Return Response": "Return Response",
5
+ "Respond and Wait for Next Webhook": "Respond and Wait for Next Webhook",
6
+ "return a response": "return a response",
7
+ "return a response and wait for the next webhook to resume the flow": "return a response and wait for the next webhook to resume the flow",
8
+ "Response Type": "Response Type",
9
+ "Response": "Response",
10
+ "Flow Execution": "Flow Execution",
11
+ "Markdown": "Markdown",
12
+ "**Respond and Wait for Next Webhook**<br> \n Check the response header (x-activepieces-resume-webhook-url) for the next webhook URL and call it to resume the flow. <br>\n ": "**Respond and Wait for Next Webhook**<br> \n Check the response header (x-activepieces-resume-webhook-url) for the next webhook URL and call it to resume the flow. <br>\n ",
13
+ "JSON": "JSON",
14
+ "Raw": "Raw",
15
+ "Redirect": "Redirect",
16
+ "Stop": "Stop",
17
+ "Respond and Continue": "Respond and Continue",
18
+ "Catch Webhook": "Catch Webhook",
19
+ "Receive incoming HTTP/webhooks using any HTTP method such as GET, POST, PUT, DELETE, etc.": "Receive incoming HTTP/webhooks using any HTTP method such as GET, POST, PUT, DELETE, etc.",
20
+ "Authentication": "Authentication",
21
+ "Authentication Fields": "Authentication Fields",
22
+ "**Live URL:**\n```text\n{{webhookUrl}}\n```\ngenerate sample data & triggers published flow.\n\n": "**Live URL:**\n```text\n{{webhookUrl}}\n```\ngenerate sample data & triggers published flow.\n\n",
23
+ "**Synchronous Requests:**\n\nIf you expect a response from this webhook, add `/sync` to the end of the URL. \nIf it takes more than 30 seconds, it will return a 408 Request Timeout response.\n\nTo return data, add an Webhook step to your flow with the Return Response action.\n": "**Synchronous Requests:**\n\nIf you expect a response from this webhook, add `/sync` to the end of the URL. \nIf it takes more than 30 seconds, it will return a 408 Request Timeout response.\n\nTo return data, add an Webhook step to your flow with the Return Response action.\n",
24
+ "\n**Test URL:**\n\nif you want to generate sample data without triggering the flow, append `/test` to your webhook URL.\n\n": "\n**Test URL:**\n\nif you want to generate sample data without triggering the flow, append `/test` to your webhook URL.\n\n",
25
+ "None": "None",
26
+ "Basic Auth": "Basic Auth",
27
+ "Header Auth": "Header Auth"
28
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "Receive HTTP requests and trigger flows using unique URLs.": "Receive HTTP requests and trigger flows using unique URLs.",
3
+ "Return Response": "Return Response",
4
+ "Respond and Wait for Next Webhook": "Respond and Wait for Next Webhook",
5
+ "return a response": "return a response",
6
+ "return a response and wait for the next webhook to resume the flow": "return a response and wait for the next webhook to resume the flow",
7
+ "Response Type": "Response Type",
8
+ "Response": "Response",
9
+ "Flow Execution": "Flow Execution",
10
+ "Markdown": "Markdown",
11
+ "**Respond and Wait for Next Webhook**<br> \n Check the response header (x-activepieces-resume-webhook-url) for the next webhook URL and call it to resume the flow. <br>\n ": "**Respond and Wait for Next Webhook**<br> \n Check the response header (x-activepieces-resume-webhook-url) for the next webhook URL and call it to resume the flow. <br>\n ",
12
+ "JSON": "JSON",
13
+ "Raw": "Raw",
14
+ "Redirect": "Redirect",
15
+ "Stop": "Stop",
16
+ "Respond and Continue": "Respond and Continue",
17
+ "Catch Webhook": "Catch Webhook",
18
+ "Receive incoming HTTP/webhooks using any HTTP method such as GET, POST, PUT, DELETE, etc.": "Receive incoming HTTP/webhooks using any HTTP method such as GET, POST, PUT, DELETE, etc.",
19
+ "Authentication": "Authentication",
20
+ "Authentication Fields": "Authentication Fields",
21
+ "**Live URL:**\n```text\n{{webhookUrl}}\n```\ngenerate sample data & triggers published flow.\n\n": "**Live URL:**\n```text\n{{webhookUrl}}\n```\ngenerate sample data & triggers published flow.\n\n",
22
+ "**Synchronous Requests:**\n\nIf you expect a response from this webhook, add `/sync` to the end of the URL. \nIf it takes more than 30 seconds, it will return a 408 Request Timeout response.\n\nTo return data, add an Webhook step to your flow with the Return Response action.\n": "**Synchronous Requests:**\n\nIf you expect a response from this webhook, add `/sync` to the end of the URL. \nIf it takes more than 30 seconds, it will return a 408 Request Timeout response.\n\nTo return data, add an Webhook step to your flow with the Return Response action.\n",
23
+ "\n**Test URL:**\n\nif you want to generate sample data without triggering the flow, append `/test` to your webhook URL.\n\n": "\n**Test URL:**\n\nif you want to generate sample data without triggering the flow, append `/test` to your webhook URL.\n\n",
24
+ "None": "None",
25
+ "Basic Auth": "Basic Auth",
26
+ "Header Auth": "Header Auth"
27
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "Webhook": "Webhook",
3
+ "Receive HTTP requests and trigger flows using unique URLs.": "Receive HTTP requests and trigger flows using unique URLs.",
4
+ "Return Response": "Return Response",
5
+ "Respond and Wait for Next Webhook": "Respond and Wait for Next Webhook",
6
+ "return a response": "return a response",
7
+ "return a response and wait for the next webhook to resume the flow": "return a response and wait for the next webhook to resume the flow",
8
+ "Response Type": "Response Type",
9
+ "Response": "Response",
10
+ "Flow Execution": "Flow Execution",
11
+ "Markdown": "Markdown",
12
+ "**Respond and Wait for Next Webhook**<br> \n Check the response header (x-activepieces-resume-webhook-url) for the next webhook URL and call it to resume the flow. <br>\n ": "**Respond and Wait for Next Webhook**<br> \n Check the response header (x-activepieces-resume-webhook-url) for the next webhook URL and call it to resume the flow. <br>\n ",
13
+ "JSON": "JSON",
14
+ "Raw": "Raw",
15
+ "Redirect": "Redirect",
16
+ "Stop": "Stop",
17
+ "Respond and Continue": "Respond and Continue",
18
+ "Catch Webhook": "Catch Webhook",
19
+ "Receive incoming HTTP/webhooks using any HTTP method such as GET, POST, PUT, DELETE, etc.": "Receive incoming HTTP/webhooks using any HTTP method such as GET, POST, PUT, DELETE, etc.",
20
+ "Authentication": "Authentication",
21
+ "Authentication Fields": "Authentication Fields",
22
+ "**Live URL:**\n```text\n{{webhookUrl}}\n```\ngenerate sample data & triggers published flow.\n\n": "**Live URL:**\n```text\n{{webhookUrl}}\n```\ngenerate sample data & triggers published flow.\n\n",
23
+ "**Synchronous Requests:**\n\nIf you expect a response from this webhook, add `/sync` to the end of the URL. \nIf it takes more than 30 seconds, it will return a 408 Request Timeout response.\n\nTo return data, add an Webhook step to your flow with the Return Response action.\n": "**Synchronous Requests:**\n\nIf you expect a response from this webhook, add `/sync` to the end of the URL. \nIf it takes more than 30 seconds, it will return a 408 Request Timeout response.\n\nTo return data, add an Webhook step to your flow with the Return Response action.\n",
24
+ "\n**Test URL:**\n\nif you want to generate sample data without triggering the flow, append `/test` to your webhook URL.\n\n": "\n**Test URL:**\n\nif you want to generate sample data without triggering the flow, append `/test` to your webhook URL.\n\n",
25
+ "None": "None",
26
+ "Basic Auth": "Basic Auth",
27
+ "Header Auth": "Header Auth"
28
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "Webhook": "Webhook",
3
+ "Receive HTTP requests and trigger flows using unique URLs.": "Receive HTTP requests and trigger flows using unique URLs.",
4
+ "Return Response": "Return Response",
5
+ "Respond and Wait for Next Webhook": "Respond and Wait for Next Webhook",
6
+ "return a response": "return a response",
7
+ "return a response and wait for the next webhook to resume the flow": "return a response and wait for the next webhook to resume the flow",
8
+ "Response Type": "Response Type",
9
+ "Response": "Response",
10
+ "Flow Execution": "Flow Execution",
11
+ "Markdown": "Markdown",
12
+ "**Respond and Wait for Next Webhook**<br> \n Check the response header (x-activepieces-resume-webhook-url) for the next webhook URL and call it to resume the flow. <br>\n ": "**Respond and Wait for Next Webhook**<br> \n Check the response header (x-activepieces-resume-webhook-url) for the next webhook URL and call it to resume the flow. <br>\n ",
13
+ "JSON": "JSON",
14
+ "Raw": "Raw",
15
+ "Redirect": "Redirect",
16
+ "Stop": "Stop",
17
+ "Respond and Continue": "Respond and Continue",
18
+ "Catch Webhook": "Catch Webhook",
19
+ "Receive incoming HTTP/webhooks using any HTTP method such as GET, POST, PUT, DELETE, etc.": "Receive incoming HTTP/webhooks using any HTTP method such as GET, POST, PUT, DELETE, etc.",
20
+ "Authentication": "Authentication",
21
+ "Authentication Fields": "Authentication Fields",
22
+ "**Live URL:**\n```text\n{{webhookUrl}}\n```\ngenerate sample data & triggers published flow.\n\n": "**Live URL:**\n```text\n{{webhookUrl}}\n```\ngenerate sample data & triggers published flow.\n\n",
23
+ "**Synchronous Requests:**\n\nIf you expect a response from this webhook, add `/sync` to the end of the URL. \nIf it takes more than 30 seconds, it will return a 408 Request Timeout response.\n\nTo return data, add an Webhook step to your flow with the Return Response action.\n": "**Synchronous Requests:**\n\nIf you expect a response from this webhook, add `/sync` to the end of the URL. \nIf it takes more than 30 seconds, it will return a 408 Request Timeout response.\n\nTo return data, add an Webhook step to your flow with the Return Response action.\n",
24
+ "\n**Test URL:**\n\nif you want to generate sample data without triggering the flow, append `/test` to your webhook URL.\n\n": "\n**Test URL:**\n\nif you want to generate sample data without triggering the flow, append `/test` to your webhook URL.\n\n",
25
+ "None": "None",
26
+ "Basic Auth": "Basic Auth",
27
+ "Header Auth": "Header Auth"
28
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "Receive HTTP requests and trigger flows using unique URLs.": "使用唯一的 URL 接收HTTP 请求和触发流。",
3
+ "Return Response": "退货回复",
4
+ "Respond and Wait for Next Webhook": "响应并等待下一个 Webhook",
5
+ "return a response": "返回响应",
6
+ "return a response and wait for the next webhook to resume the flow": "返回响应并等待下一个 web 钩子以恢复流",
7
+ "Response Type": "响应类型",
8
+ "Response": "答复",
9
+ "Flow Execution": "流执行",
10
+ "Markdown": "Markdown",
11
+ "**Respond and Wait for Next Webhook**<br> \n Check the response header (x-activepieces-resume-webhook-url) for the next webhook URL and call it to resume the flow. <br>\n ": "**响应并等待下一个 Webhook**<br> \n 请检查下一个 webhook URL 的响应头(x-activethes-resume-webhook-url) 并调用它来恢复流程。 <br>\n ",
12
+ "JSON": "JSON",
13
+ "Raw": "原始文件",
14
+ "Redirect": "重定向",
15
+ "Stop": "停止",
16
+ "Respond and Continue": "响应并继续",
17
+ "Catch Webhook": "捕获Webhook",
18
+ "Receive incoming HTTP/webhooks using any HTTP method such as GET, POST, PUT, DELETE, etc.": "使用 GET、POST、PUT、DELETE等任何HTTP 方法接收传入的 HTTP/webhooks 。",
19
+ "Authentication": "认证",
20
+ "Authentication Fields": "身份验证字段",
21
+ "**Live URL:**\n```text\n{{webhookUrl}}\n```\ngenerate sample data & triggers published flow.\n\n": "**Live URL:**\n```text\n{{webhookUrl}}\n```\ngenerate sample data & triggers published flow.\n\n",
22
+ "**Synchronous Requests:**\n\nIf you expect a response from this webhook, add `/sync` to the end of the URL. \nIf it takes more than 30 seconds, it will return a 408 Request Timeout response.\n\nTo return data, add an Webhook step to your flow with the Return Response action.\n": "**Synchronous Requests:**\n\nIf you expect a response from this webhook, add `/sync` to the end of the URL. \nIf it takes more than 30 seconds, it will return a 408 Request Timeout response.\n\nTo return data, add an Webhook step to your flow with the Return Response action.\n",
23
+ "\n**Test URL:**\n\nif you want to generate sample data without triggering the flow, append `/test` to your webhook URL.\n\n": "\n**Test URL:**\n\nif you want to generate sample data without triggering the flow, append `/test` to your webhook URL.\n\n",
24
+ "None": "无",
25
+ "Basic Auth": "基本认证",
26
+ "Header Auth": "头部认证"
27
+ }
package/src/index.ts ADDED
@@ -0,0 +1,17 @@
1
+ import { createPiece, PieceAuth } from '@guayaba/workflows-framework';
2
+ import { catchWebhook } from './lib/triggers/catch-hook';
3
+ import { PieceCategory } from '@guayaba/workflows-shared';
4
+ import { returnResponse } from './lib/actions/return-response';
5
+ import { returnResponseAndWaitForNextWebhook } from './lib/actions/return-response-and-wait-for-next-webhook';
6
+
7
+ export const webhook = createPiece({
8
+ displayName: 'Webhook',
9
+ description: 'Receive HTTP requests and trigger flows using unique URLs.',
10
+ auth: PieceAuth.None(),
11
+ categories: [PieceCategory.CORE],
12
+ minimumSupportedRelease: '0.82.0',
13
+ logoUrl: 'https://cdn.activepieces.com/pieces/new-core/webhooks.svg',
14
+ authors: ['abuaboud', 'pfernandez98', 'kishanprmr','AbdulTheActivePiecer'],
15
+ actions: [returnResponse,returnResponseAndWaitForNextWebhook],
16
+ triggers: [catchWebhook],
17
+ });
@@ -0,0 +1,163 @@
1
+ import {
2
+ DynamicPropsValue,
3
+ PieceAuth,
4
+ Property,
5
+ createAction,
6
+ } from '@guayaba/workflows-framework';
7
+ import { ExecutionType, StopResponse } from '@guayaba/workflows-shared';
8
+ import { StatusCodes } from 'http-status-codes';
9
+
10
+ enum ResponseType {
11
+ JSON = 'json',
12
+ RAW = 'raw',
13
+ REDIRECT = 'redirect',
14
+ }
15
+
16
+
17
+ const RESUME_WEBHOOK_HEADER = 'x-activepieces-resume-webhook-url';
18
+ export const returnResponseAndWaitForNextWebhook = createAction({
19
+ name: 'return_response_and_wait_for_next_webhook',
20
+ displayName: 'Respond and Wait for Next Webhook',
21
+ description: 'return a response and wait for the next webhook to resume the flow',
22
+ props: {
23
+ markdown: Property.MarkDown({
24
+ value: `**Respond and Wait for Next Webhook**<br>
25
+ Check the response header (${RESUME_WEBHOOK_HEADER}) for the next webhook URL and call it to resume the flow. <br>
26
+ `,
27
+ }),
28
+ responseType: Property.StaticDropdown({
29
+ displayName: 'Response Type',
30
+ required: false,
31
+ defaultValue: 'json',
32
+ options: {
33
+ disabled: false,
34
+ options: [
35
+ {
36
+ label: 'JSON',
37
+ value: ResponseType.JSON,
38
+ },
39
+ {
40
+ label: 'Raw',
41
+ value: ResponseType.RAW,
42
+ },
43
+ {
44
+ label: 'Redirect',
45
+ value: ResponseType.REDIRECT,
46
+ },
47
+ ],
48
+ },
49
+ }),
50
+ fields: Property.DynamicProperties({
51
+ auth: PieceAuth.None(),
52
+ displayName: 'Response',
53
+ refreshers: ['responseType'],
54
+ required: true,
55
+ props: async ({ responseType }) => {
56
+ if (!responseType) return {};
57
+
58
+ const bodyTypeInput = responseType as unknown as ResponseType;
59
+
60
+ const fields: DynamicPropsValue = {};
61
+
62
+ if (bodyTypeInput !== ResponseType.REDIRECT) {
63
+ fields['status'] = Property.Number({
64
+ displayName: 'Status',
65
+ required: false,
66
+ defaultValue: 200,
67
+ });
68
+ fields['headers'] = Property.Object({
69
+ displayName: 'Headers',
70
+ required: false,
71
+ });
72
+ }
73
+
74
+ switch (bodyTypeInput) {
75
+ case ResponseType.JSON:
76
+ fields['body'] = Property.Json({
77
+ displayName: 'JSON Body',
78
+ required: true,
79
+ });
80
+ break;
81
+ case ResponseType.RAW:
82
+ fields['body'] = Property.LongText({
83
+ displayName: 'Raw Body',
84
+ required: true,
85
+ });
86
+ break;
87
+ case ResponseType.REDIRECT:
88
+ fields['body'] = Property.LongText({
89
+ displayName: 'Redirect URL',
90
+ required: true,
91
+ });
92
+ break;
93
+ }
94
+ return fields;
95
+ },
96
+ }),
97
+ },
98
+
99
+ async run(context) {
100
+ const { fields, responseType } = context.propsValue;
101
+ const bodyInput = fields ['body'];
102
+ const headers = fields['headers'] ?? {};
103
+ const status = fields['status'];
104
+ const response: StopResponse = {
105
+ status: status ?? StatusCodes.OK,
106
+ headers,
107
+ };
108
+
109
+ switch (responseType) {
110
+ case ResponseType.JSON:
111
+ response.body = praseToJson(bodyInput);
112
+ break;
113
+ case ResponseType.RAW:
114
+ response.body = bodyInput;
115
+ break;
116
+ case ResponseType.REDIRECT:
117
+ response.status = StatusCodes.MOVED_PERMANENTLY;
118
+ response.headers = { ...response.headers, Location: ensureProtocol(bodyInput) };
119
+ response.body = bodyInput;
120
+ break;
121
+ }
122
+
123
+ if(context.executionType === ExecutionType.BEGIN){
124
+ const waitpoint = await context.run.createWaitpoint({
125
+ type: 'WEBHOOK',
126
+ responseToSend: response,
127
+ });
128
+ headers[RESUME_WEBHOOK_HEADER] = waitpoint.buildResumeUrl({
129
+ queryParams: {
130
+ created: new Date().toISOString(),
131
+ runId: context.run.id,
132
+ },
133
+ sync: true,
134
+ });
135
+ context.run.waitForWaitpoint(waitpoint.id);
136
+ return {
137
+ nextWebhookUrl: headers[RESUME_WEBHOOK_HEADER],
138
+ };
139
+ }
140
+ else {
141
+ return {
142
+ body: context.resumePayload.body,
143
+ headers: context.resumePayload.headers,
144
+ queryParams: context.resumePayload.queryParams,
145
+ }
146
+ }
147
+ },
148
+ });
149
+
150
+ function praseToJson(body: unknown) {
151
+ if (typeof body === 'string') {
152
+ return JSON.parse(body);
153
+ }
154
+ return JSON.parse(JSON.stringify(body));
155
+ }
156
+
157
+ function ensureProtocol(url: string): string {
158
+ if (!url.startsWith('http://') && !url.startsWith('https://')) {
159
+ return `https://${url}`;
160
+ }
161
+ return url;
162
+ }
163
+
@@ -0,0 +1,171 @@
1
+ import {
2
+ DynamicPropsValue,
3
+ PieceAuth,
4
+ Property,
5
+ createAction,
6
+ } from '@guayaba/workflows-framework';
7
+ import { StopResponse } from '@guayaba/workflows-shared';
8
+ import { StatusCodes } from 'http-status-codes';
9
+
10
+ enum ResponseType {
11
+ JSON = 'json',
12
+ RAW = 'raw',
13
+ REDIRECT = 'redirect',
14
+ }
15
+
16
+ enum FlowExecution {
17
+ STOP = 'stop',
18
+ RESPOND = 'respond',
19
+ }
20
+
21
+ export const returnResponse = createAction({
22
+ name: 'return_response',
23
+ displayName: 'Return Response',
24
+ description: 'return a response',
25
+ props: {
26
+ responseType: Property.StaticDropdown({
27
+ displayName: 'Response Type',
28
+ required: false,
29
+ defaultValue: 'json',
30
+ options: {
31
+ disabled: false,
32
+ options: [
33
+ {
34
+ label: 'JSON',
35
+ value: ResponseType.JSON,
36
+ },
37
+ {
38
+ label: 'Raw',
39
+ value: ResponseType.RAW,
40
+ },
41
+ {
42
+ label: 'Redirect',
43
+ value: ResponseType.REDIRECT,
44
+ },
45
+ ],
46
+ },
47
+ }),
48
+ fields: Property.DynamicProperties({
49
+ auth: PieceAuth.None(),
50
+ displayName: 'Response',
51
+ refreshers: ['responseType'],
52
+ required: true,
53
+ props: async ({ responseType }) => {
54
+ if (!responseType) return {};
55
+
56
+ const bodyTypeInput = responseType as unknown as ResponseType;
57
+
58
+ const fields: DynamicPropsValue = {};
59
+
60
+ if (bodyTypeInput !== ResponseType.REDIRECT) {
61
+ fields['status'] = Property.Number({
62
+ displayName: 'Status',
63
+ required: false,
64
+ defaultValue: 200,
65
+ });
66
+ fields['headers'] = Property.Object({
67
+ displayName: 'Headers',
68
+ required: false,
69
+ });
70
+ }
71
+
72
+ switch (bodyTypeInput) {
73
+ case ResponseType.JSON:
74
+ fields['body'] = Property.Json({
75
+ displayName: 'JSON Body',
76
+ required: true,
77
+ });
78
+ break;
79
+ case ResponseType.RAW:
80
+ fields['body'] = Property.LongText({
81
+ displayName: 'Raw Body',
82
+ required: true,
83
+ });
84
+ break;
85
+ case ResponseType.REDIRECT:
86
+ fields['body'] = Property.LongText({
87
+ displayName: 'Redirect URL',
88
+ required: true,
89
+ });
90
+ break;
91
+ }
92
+ return fields;
93
+ },
94
+ }),
95
+ respond: Property.StaticDropdown({
96
+ displayName: 'Flow Execution',
97
+ required: false,
98
+ defaultValue: FlowExecution.STOP,
99
+ options: {
100
+ disabled: false,
101
+ options: [
102
+ { label: 'Stop', value: FlowExecution.STOP },
103
+ { label: 'Respond and Continue', value: FlowExecution.RESPOND },
104
+ ],
105
+ },
106
+ }),
107
+ },
108
+
109
+ async run(context) {
110
+ const { fields, responseType, respond } = context.propsValue;
111
+ const bodyInput = fields ['body'];
112
+ const headers = fields['headers']?? {};
113
+ const status = fields['status'];
114
+
115
+
116
+ const response: StopResponse = {
117
+ status: status ?? StatusCodes.OK,
118
+ headers,
119
+ };
120
+
121
+ switch (responseType) {
122
+ case ResponseType.JSON:
123
+ response.body = praseToJson(bodyInput);
124
+ break;
125
+ case ResponseType.RAW:
126
+ response.body = bodyInput;
127
+ break;
128
+ case ResponseType.REDIRECT:
129
+ response.status = StatusCodes.MOVED_PERMANENTLY;
130
+ response.headers = { ...response.headers, Location: ensureProtocol(bodyInput) };
131
+ response.body = bodyInput;
132
+ break;
133
+ }
134
+
135
+ switch(respond){
136
+ case FlowExecution.STOP:
137
+ {
138
+ context.run.stop({
139
+ response,
140
+ });
141
+ break;
142
+ }
143
+ case FlowExecution.RESPOND:
144
+ {
145
+ context.run.respond({
146
+ response,
147
+ });
148
+ break;
149
+ }
150
+ case undefined:
151
+ break;
152
+ }
153
+
154
+
155
+ return response;
156
+ },
157
+ });
158
+
159
+ function praseToJson(body: unknown) {
160
+ if (typeof body === 'string') {
161
+ return JSON.parse(body);
162
+ }
163
+ return JSON.parse(JSON.stringify(body));
164
+ }
165
+
166
+ function ensureProtocol(url: string): string {
167
+ if (!url.startsWith('http://') && !url.startsWith('https://')) {
168
+ return `https://${url}`;
169
+ }
170
+ return url;
171
+ }