n8n-nodes-airprocess 0.1.21 → 0.1.22

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.
@@ -8,8 +8,10 @@ const CUSTOM_URL_EXPRESSION = '={{ $parameter.customUrl.startsWith("http") ? $pa
8
8
  const CUSTOM_BODY_EXPRESSION = '={{ $parameter.customSendBody ? (typeof $parameter.customBody === "string" ? JSON.parse($parameter.customBody) : $parameter.customBody) : undefined }}';
9
9
  const AUTHORIZATION_HEADER_EXPRESSION = '={{ undefined }}';
10
10
  const CUSTOM_HEADERS_EXPRESSION = '={{ $parameter.customSendHeaders ? (typeof $parameter.customHeaders === "string" ? JSON.parse($parameter.customHeaders) : $parameter.customHeaders) : {} }}';
11
+ const GET_REQUEST_OPTIONS_PARAMETER = 'getRequestOptions';
12
+ const POST_REQUEST_OPTIONS_PARAMETER = 'postRequestOptions';
13
+ const CUSTOM_REQUEST_OPTIONS_PARAMETER = 'customRequestOptions';
11
14
  const RESOLVE_COLLECTION_VALUE_EXPRESSION = '(value) => typeof value === "string" && value.startsWith("={{") ? $evaluateExpression(value.slice(1)) : value';
12
- const CREATE_RECORD_BODY_EXPRESSION = `={{ (() => { const resolveCollectionValue = ${RESOLVE_COLLECTION_VALUE_EXPRESSION}; const generatedId = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => { const r = Math.floor(Math.random() * 16); const v = c === "x" ? r : (r & 0x3) | 0x8; return v.toString(16); }); if ($parameter.createBodyMode === "fields") { const selectedFields = ($parameter.createFields && $parameter.createFields.field) ? $parameter.createFields.field : []; const payloadFromFields = selectedFields.reduce((acc, current) => { const fieldId = resolveCollectionValue(current.fieldId); if (fieldId) { acc[fieldId] = resolveCollectionValue(current.value); } return acc; }, {}); return { ...payloadFromFields, id: generatedId }; } const payload = typeof $parameter.bodyCreate === "string" ? JSON.parse($parameter.bodyCreate) : $parameter.bodyCreate; return { ...payload, id: generatedId }; })() }}`;
13
15
  const FIND_RECORDS_MONGO_BODY_EXPRESSION = `={{ (() => { const resolveCollectionValue = ${RESOLVE_COLLECTION_VALUE_EXPRESSION}; const mode = $parameter.findFilterMode ?? "fields"; const filter = mode === "json" ? (typeof $parameter.findFilterJson === "string" ? JSON.parse($parameter.findFilterJson) : ($parameter.findFilterJson ?? {})) : (($parameter.findFields && $parameter.findFields.field) ? $parameter.findFields.field : []).reduce((acc, current) => { const fieldId = resolveCollectionValue(current.fieldId); if (fieldId) { acc[fieldId] = resolveCollectionValue(current.value); } return acc; }, {}); return { operation: "search", filterSyntax: "mongo", skip: Number($parameter.findSkip ?? 0), limit: Number($parameter.findLimit ?? 10), filter }; })() }}`;
14
16
  const UPDATE_RECORD_BODY_EXPRESSION = `={{ (() => { const resolveCollectionValue = ${RESOLVE_COLLECTION_VALUE_EXPRESSION}; if ($parameter.updateBodyMode === "fields") { const selectedFields = ($parameter.updateFields && $parameter.updateFields.field) ? $parameter.updateFields.field : []; return selectedFields.reduce((acc, current) => { const fieldId = resolveCollectionValue(current.fieldId); if (fieldId) { acc[fieldId] = resolveCollectionValue(current.value); } return acc; }, {}); } return typeof $parameter.bodyUpdate === "string" ? JSON.parse($parameter.bodyUpdate) : $parameter.bodyUpdate; })() }}`;
15
17
  function toModelOption(item) {
@@ -93,6 +95,238 @@ function extractSingleFromResponse(response) {
93
95
  }
94
96
  return undefined;
95
97
  }
98
+ function generateUuid() {
99
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (character) => {
100
+ const random = Math.floor(Math.random() * 16);
101
+ const value = character === 'x' ? random : (random & 0x3) | 0x8;
102
+ return value.toString(16);
103
+ });
104
+ }
105
+ function stringifyBodyValue(value) {
106
+ if (value === null || value === undefined) {
107
+ return '';
108
+ }
109
+ if (typeof value === 'object') {
110
+ return JSON.stringify(value);
111
+ }
112
+ return String(value);
113
+ }
114
+ function getCreateFieldPayload(executeFunctions, parameterName) {
115
+ const parameterValue = executeFunctions.getNodeParameter(parameterName, {});
116
+ const selectedFields = Array.isArray(parameterValue.field) ? parameterValue.field : [];
117
+ const payload = {};
118
+ for (const current of selectedFields) {
119
+ const fieldId = typeof current.fieldId === 'string'
120
+ ? current.fieldId.trim()
121
+ : current.fieldId === undefined || current.fieldId === null
122
+ ? ''
123
+ : String(current.fieldId).trim();
124
+ if (fieldId.length === 0) {
125
+ continue;
126
+ }
127
+ payload[fieldId] = current.value;
128
+ }
129
+ return payload;
130
+ }
131
+ function getCreateRecordJsonPayload(executeFunctions) {
132
+ const bodyMode = executeFunctions.getNodeParameter('createBodyMode', 'json');
133
+ if (bodyMode === 'fields') {
134
+ return {
135
+ ...getCreateFieldPayload(executeFunctions, 'createFields'),
136
+ id: generateUuid(),
137
+ };
138
+ }
139
+ const bodyValue = executeFunctions.getNodeParameter('bodyCreate', {});
140
+ const payload = typeof bodyValue === 'string'
141
+ ? JSON.parse(bodyValue)
142
+ : (bodyValue !== null && bodyValue !== void 0 ? bodyValue : {});
143
+ return {
144
+ ...payload,
145
+ id: generateUuid(),
146
+ };
147
+ }
148
+ function getCreateRecordFormPayload(executeFunctions) {
149
+ return {
150
+ ...getCreateFieldPayload(executeFunctions, 'createFormFields'),
151
+ id: generateUuid(),
152
+ };
153
+ }
154
+ function getCustomParameterPayload(executeFunctions) {
155
+ const parameterValue = executeFunctions.getNodeParameter('customFormFields', {});
156
+ const parameters = Array.isArray(parameterValue.parameter) ? parameterValue.parameter : [];
157
+ const payload = {};
158
+ for (const current of parameters) {
159
+ const name = typeof current.name === 'string'
160
+ ? current.name.trim()
161
+ : current.name === undefined || current.name === null
162
+ ? ''
163
+ : String(current.name).trim();
164
+ if (name.length === 0) {
165
+ continue;
166
+ }
167
+ payload[name] = current.value;
168
+ }
169
+ return payload;
170
+ }
171
+ function getCustomFormDataFields(executeFunctions) {
172
+ const parameterValue = executeFunctions.getNodeParameter('customFormDataFields', {});
173
+ const bodyFields = Array.isArray(parameterValue.bodyField) ? parameterValue.bodyField : [];
174
+ return bodyFields
175
+ .map((current) => {
176
+ const name = typeof current.name === 'string'
177
+ ? current.name.trim()
178
+ : current.name === undefined || current.name === null
179
+ ? ''
180
+ : String(current.name).trim();
181
+ const type = current.type === 'binaryFile' ? 'binaryFile' : 'formData';
182
+ const inputDataFieldName = typeof current.inputDataFieldName === 'string'
183
+ ? current.inputDataFieldName.trim()
184
+ : current.inputDataFieldName === undefined || current.inputDataFieldName === null
185
+ ? undefined
186
+ : String(current.inputDataFieldName).trim();
187
+ return {
188
+ inputDataFieldName,
189
+ name,
190
+ type,
191
+ value: current.value,
192
+ };
193
+ })
194
+ .filter((field) => field.name.length > 0);
195
+ }
196
+ async function configureCreateRecordRequest(requestOptions) {
197
+ var _a;
198
+ const bodyContentType = this.getNodeParameter('createBodyContentType', 'json');
199
+ const headers = {
200
+ ...((_a = requestOptions.headers) !== null && _a !== void 0 ? _a : {}),
201
+ };
202
+ switch (bodyContentType) {
203
+ case 'binaryFile': {
204
+ const inputDataFieldName = this.getNodeParameter('createBinaryInputDataFieldName', 'data');
205
+ const contentType = this.getNodeParameter('createBinaryContentType', 'application/octet-stream');
206
+ requestOptions.body = await this.helpers.getBinaryDataBuffer(inputDataFieldName);
207
+ headers['Content-Type'] = contentType;
208
+ break;
209
+ }
210
+ case 'formData': {
211
+ const payload = getCreateRecordFormPayload(this);
212
+ const formData = new FormData();
213
+ for (const [key, value] of Object.entries(payload)) {
214
+ formData.append(key, stringifyBodyValue(value));
215
+ }
216
+ requestOptions.body = formData;
217
+ delete headers['Content-Type'];
218
+ break;
219
+ }
220
+ case 'formUrlencoded': {
221
+ const payload = getCreateRecordFormPayload(this);
222
+ const params = new URLSearchParams();
223
+ for (const [key, value] of Object.entries(payload)) {
224
+ params.append(key, stringifyBodyValue(value));
225
+ }
226
+ requestOptions.body = params;
227
+ headers['Content-Type'] = 'application/x-www-form-urlencoded';
228
+ break;
229
+ }
230
+ case 'raw': {
231
+ const rawBody = this.getNodeParameter('createRawBody', '');
232
+ const rawContentType = this.getNodeParameter('createRawContentType', 'text/plain');
233
+ requestOptions.body = rawBody;
234
+ headers['Content-Type'] = rawContentType;
235
+ break;
236
+ }
237
+ case 'json':
238
+ default: {
239
+ requestOptions.body = getCreateRecordJsonPayload(this);
240
+ headers['Content-Type'] = 'application/json';
241
+ break;
242
+ }
243
+ }
244
+ requestOptions.headers = headers;
245
+ return requestOptions;
246
+ }
247
+ async function configureCustomTypedBodyRequest(requestOptions) {
248
+ var _a;
249
+ const sendBody = this.getNodeParameter('customSendBody', false);
250
+ if (!sendBody) {
251
+ return requestOptions;
252
+ }
253
+ const bodyContentType = this.getNodeParameter('customBodyContentType', 'json');
254
+ const headers = {
255
+ ...((_a = requestOptions.headers) !== null && _a !== void 0 ? _a : {}),
256
+ };
257
+ switch (bodyContentType) {
258
+ case 'binaryFile': {
259
+ const inputDataFieldName = this.getNodeParameter('customBinaryInputDataFieldName', 'data');
260
+ const contentType = this.getNodeParameter('customBinaryContentType', 'application/octet-stream');
261
+ requestOptions.body = await this.helpers.getBinaryDataBuffer(inputDataFieldName);
262
+ headers['Content-Type'] = contentType;
263
+ break;
264
+ }
265
+ case 'formData': {
266
+ const payload = getCustomFormDataFields(this);
267
+ const formData = new FormData();
268
+ for (const field of payload) {
269
+ if (field.type === 'binaryFile') {
270
+ if (!field.inputDataFieldName) {
271
+ continue;
272
+ }
273
+ const binaryMetadata = this.helpers.assertBinaryData(field.inputDataFieldName);
274
+ const buffer = await this.helpers.getBinaryDataBuffer(field.inputDataFieldName);
275
+ const blob = new Blob([buffer], {
276
+ type: binaryMetadata.mimeType || 'application/octet-stream',
277
+ });
278
+ formData.append(field.name, blob, binaryMetadata.fileName || field.inputDataFieldName);
279
+ continue;
280
+ }
281
+ formData.append(field.name, stringifyBodyValue(field.value));
282
+ }
283
+ requestOptions.body = formData;
284
+ delete headers['Content-Type'];
285
+ break;
286
+ }
287
+ case 'formUrlencoded': {
288
+ const payload = getCustomParameterPayload(this);
289
+ const params = new URLSearchParams();
290
+ for (const [key, value] of Object.entries(payload)) {
291
+ params.append(key, stringifyBodyValue(value));
292
+ }
293
+ requestOptions.body = params;
294
+ headers['Content-Type'] = 'application/x-www-form-urlencoded';
295
+ break;
296
+ }
297
+ case 'raw': {
298
+ const rawBody = this.getNodeParameter('customRawBody', '');
299
+ const rawContentType = this.getNodeParameter('customRawContentType', 'text/plain');
300
+ requestOptions.body = rawBody;
301
+ headers['Content-Type'] = rawContentType;
302
+ break;
303
+ }
304
+ case 'json':
305
+ default: {
306
+ const bodyValue = this.getNodeParameter('customBody', {});
307
+ requestOptions.body =
308
+ typeof bodyValue === 'string'
309
+ ? JSON.parse(bodyValue)
310
+ : (bodyValue !== null && bodyValue !== void 0 ? bodyValue : {});
311
+ headers['Content-Type'] = 'application/json';
312
+ break;
313
+ }
314
+ }
315
+ requestOptions.headers = headers;
316
+ return requestOptions;
317
+ }
318
+ function buildHttpNodeLikeRequestOptions(parameterName) {
319
+ return {
320
+ encoding: `={{ $parameter.${parameterName}.responseFormat === "file" ? "arraybuffer" : ($parameter.${parameterName}.responseFormat === "json" ? "json" : ($parameter.${parameterName}.responseFormat === "text" ? "text" : undefined)) }}`,
321
+ skipSslCertificateValidation: `={{ $parameter.${parameterName}.ignoreSslIssues ?? false }}`,
322
+ disableFollowRedirect: `={{ $parameter.${parameterName}.followRedirects === false }}`,
323
+ maxRedirects: `={{ $parameter.${parameterName}.followRedirects === false ? undefined : $parameter.${parameterName}.maxRedirects }}`,
324
+ returnFullResponse: `={{ $parameter.${parameterName}.includeHeadersAndStatus ?? false }}`,
325
+ ignoreHttpStatusErrors: `={{ $parameter.${parameterName}.neverError ?? false }}`,
326
+ proxy: `={{ (() => { const proxyValue = $parameter.${parameterName}.proxy; if (!proxyValue) { return undefined; } const normalized = proxyValue.includes("://") ? proxyValue : "http://" + proxyValue; const parsed = new URL(normalized); return { protocol: parsed.protocol.replace(":", ""), host: parsed.hostname, port: Number(parsed.port || (parsed.protocol === "https:" ? 443 : 80)), auth: parsed.username ? { username: decodeURIComponent(parsed.username), password: decodeURIComponent(parsed.password) } : undefined }; })() }}`,
327
+ timeout: `={{ $parameter.${parameterName}.timeout ?? undefined }}`,
328
+ };
329
+ }
96
330
  function resolveModelId(models, selectedModelId) {
97
331
  var _a;
98
332
  const matchingModel = models.find((model) => model.modelID === selectedModelId || model.modelId === selectedModelId || model.id === selectedModelId);
@@ -235,6 +469,7 @@ class AirProcess {
235
469
  headers: {
236
470
  Authorization: AUTHORIZATION_HEADER_EXPRESSION,
237
471
  },
472
+ ...buildHttpNodeLikeRequestOptions(GET_REQUEST_OPTIONS_PARAMETER),
238
473
  },
239
474
  },
240
475
  },
@@ -249,6 +484,7 @@ class AirProcess {
249
484
  headers: {
250
485
  Authorization: AUTHORIZATION_HEADER_EXPRESSION,
251
486
  },
487
+ ...buildHttpNodeLikeRequestOptions(GET_REQUEST_OPTIONS_PARAMETER),
252
488
  },
253
489
  },
254
490
  },
@@ -263,6 +499,7 @@ class AirProcess {
263
499
  headers: {
264
500
  Authorization: AUTHORIZATION_HEADER_EXPRESSION,
265
501
  },
502
+ ...buildHttpNodeLikeRequestOptions(GET_REQUEST_OPTIONS_PARAMETER),
266
503
  },
267
504
  },
268
505
  },
@@ -277,6 +514,7 @@ class AirProcess {
277
514
  headers: {
278
515
  Authorization: AUTHORIZATION_HEADER_EXPRESSION,
279
516
  },
517
+ ...buildHttpNodeLikeRequestOptions(GET_REQUEST_OPTIONS_PARAMETER),
280
518
  },
281
519
  },
282
520
  },
@@ -291,6 +529,7 @@ class AirProcess {
291
529
  headers: {
292
530
  Authorization: AUTHORIZATION_HEADER_EXPRESSION,
293
531
  },
532
+ ...buildHttpNodeLikeRequestOptions(GET_REQUEST_OPTIONS_PARAMETER),
294
533
  },
295
534
  },
296
535
  },
@@ -305,6 +544,7 @@ class AirProcess {
305
544
  headers: {
306
545
  Authorization: AUTHORIZATION_HEADER_EXPRESSION,
307
546
  },
547
+ ...buildHttpNodeLikeRequestOptions(GET_REQUEST_OPTIONS_PARAMETER),
308
548
  },
309
549
  },
310
550
  },
@@ -319,6 +559,7 @@ class AirProcess {
319
559
  headers: {
320
560
  Authorization: AUTHORIZATION_HEADER_EXPRESSION,
321
561
  },
562
+ ...buildHttpNodeLikeRequestOptions(GET_REQUEST_OPTIONS_PARAMETER),
322
563
  },
323
564
  },
324
565
  },
@@ -333,6 +574,7 @@ class AirProcess {
333
574
  headers: {
334
575
  Authorization: AUTHORIZATION_HEADER_EXPRESSION,
335
576
  },
577
+ ...buildHttpNodeLikeRequestOptions(GET_REQUEST_OPTIONS_PARAMETER),
336
578
  },
337
579
  },
338
580
  },
@@ -358,11 +600,14 @@ class AirProcess {
358
600
  request: {
359
601
  method: 'POST',
360
602
  url: '=/{{$parameter.modelIdCreate}}',
361
- body: CREATE_RECORD_BODY_EXPRESSION,
603
+ body: '={{ {} }}',
362
604
  headers: {
363
605
  Authorization: AUTHORIZATION_HEADER_EXPRESSION,
364
- 'Content-Type': 'application/json',
365
606
  },
607
+ ...buildHttpNodeLikeRequestOptions(POST_REQUEST_OPTIONS_PARAMETER),
608
+ },
609
+ send: {
610
+ preSend: [configureCreateRecordRequest],
366
611
  },
367
612
  },
368
613
  },
@@ -379,6 +624,7 @@ class AirProcess {
379
624
  Authorization: AUTHORIZATION_HEADER_EXPRESSION,
380
625
  'Content-Type': 'application/json',
381
626
  },
627
+ ...buildHttpNodeLikeRequestOptions(POST_REQUEST_OPTIONS_PARAMETER),
382
628
  },
383
629
  },
384
630
  },
@@ -491,8 +737,23 @@ class AirProcess {
491
737
  request: {
492
738
  method: 'GET',
493
739
  url: CUSTOM_URL_EXPRESSION,
494
- body: CUSTOM_BODY_EXPRESSION,
740
+ body: '={{ {} }}',
495
741
  headers: CUSTOM_HEADERS_EXPRESSION,
742
+ ...buildHttpNodeLikeRequestOptions(CUSTOM_REQUEST_OPTIONS_PARAMETER),
743
+ },
744
+ send: {
745
+ preSend: [configureCustomTypedBodyRequest],
746
+ },
747
+ output: {
748
+ postReceive: [
749
+ {
750
+ type: 'binaryData',
751
+ enabled: '={{ $parameter.customRequestOptions.responseFormat === "file" }}',
752
+ properties: {
753
+ destinationProperty: '={{ $parameter.customRequestOptions.responseBinaryPropertyName || "data" }}',
754
+ },
755
+ },
756
+ ],
496
757
  },
497
758
  },
498
759
  },
@@ -517,14 +778,274 @@ class AirProcess {
517
778
  request: {
518
779
  method: 'POST',
519
780
  url: CUSTOM_URL_EXPRESSION,
520
- body: CUSTOM_BODY_EXPRESSION,
781
+ body: '={{ {} }}',
521
782
  headers: CUSTOM_HEADERS_EXPRESSION,
783
+ ...buildHttpNodeLikeRequestOptions(CUSTOM_REQUEST_OPTIONS_PARAMETER),
784
+ },
785
+ send: {
786
+ preSend: [configureCustomTypedBodyRequest],
787
+ },
788
+ output: {
789
+ postReceive: [
790
+ {
791
+ type: 'binaryData',
792
+ enabled: '={{ $parameter.customRequestOptions.responseFormat === "file" }}',
793
+ properties: {
794
+ destinationProperty: '={{ $parameter.customRequestOptions.responseBinaryPropertyName || "data" }}',
795
+ },
796
+ },
797
+ ],
522
798
  },
523
799
  },
524
800
  },
525
801
  ],
526
802
  default: 'customGet',
527
803
  },
804
+ {
805
+ displayName: 'Options',
806
+ name: CUSTOM_REQUEST_OPTIONS_PARAMETER,
807
+ type: 'collection',
808
+ placeholder: 'Add option',
809
+ default: {},
810
+ displayOptions: {
811
+ show: {
812
+ resource: ['custom'],
813
+ operation: ['customGet', 'customPost'],
814
+ },
815
+ },
816
+ options: [
817
+ {
818
+ displayName: 'Follow Redirects',
819
+ name: 'followRedirects',
820
+ type: 'boolean',
821
+ default: true,
822
+ description: 'Whether to follow HTTP redirects',
823
+ },
824
+ {
825
+ displayName: 'Ignore SSL Issues',
826
+ name: 'ignoreSslIssues',
827
+ type: 'boolean',
828
+ default: false,
829
+ description: 'Whether to allow the request even when SSL certificate validation fails',
830
+ },
831
+ {
832
+ displayName: 'Include Response Headers and Status',
833
+ name: 'includeHeadersAndStatus',
834
+ type: 'boolean',
835
+ default: false,
836
+ description: 'Whether to return the full response instead of only the body',
837
+ },
838
+ {
839
+ displayName: 'Max Redirects',
840
+ name: 'maxRedirects',
841
+ type: 'number',
842
+ default: 21,
843
+ displayOptions: {
844
+ show: {
845
+ followRedirects: [true],
846
+ },
847
+ },
848
+ description: 'Maximum number of redirects to follow',
849
+ },
850
+ {
851
+ displayName: 'Never Error',
852
+ name: 'neverError',
853
+ type: 'boolean',
854
+ default: false,
855
+ description: 'Whether to return the response even when the status code is not 2xx',
856
+ },
857
+ {
858
+ displayName: 'Proxy',
859
+ name: 'proxy',
860
+ type: 'string',
861
+ default: '',
862
+ placeholder: 'http://proxy.example.com:8080',
863
+ description: 'HTTP proxy to use for this request',
864
+ },
865
+ {
866
+ displayName: 'Response Binary Property',
867
+ name: 'responseBinaryPropertyName',
868
+ type: 'string',
869
+ default: 'data',
870
+ displayOptions: {
871
+ show: {
872
+ responseFormat: ['file'],
873
+ },
874
+ },
875
+ description: 'Name of the binary property where the downloaded file will be stored',
876
+ },
877
+ {
878
+ displayName: 'Response Format',
879
+ name: 'responseFormat',
880
+ type: 'options',
881
+ options: [
882
+ {
883
+ name: 'Autodetect',
884
+ value: 'autodetect',
885
+ },
886
+ {
887
+ name: 'File',
888
+ value: 'file',
889
+ },
890
+ {
891
+ name: 'JSON',
892
+ value: 'json',
893
+ },
894
+ {
895
+ name: 'Text',
896
+ value: 'text',
897
+ },
898
+ ],
899
+ default: 'autodetect',
900
+ description: 'How to interpret the response body',
901
+ },
902
+ {
903
+ displayName: 'Timeout',
904
+ name: 'timeout',
905
+ type: 'number',
906
+ default: 30000,
907
+ description: 'Time to wait for the initial response in milliseconds',
908
+ },
909
+ ],
910
+ },
911
+ {
912
+ displayName: 'Options',
913
+ name: GET_REQUEST_OPTIONS_PARAMETER,
914
+ type: 'collection',
915
+ placeholder: 'Add option',
916
+ default: {},
917
+ displayOptions: {
918
+ show: {
919
+ resource: ['get'],
920
+ },
921
+ },
922
+ options: [
923
+ {
924
+ displayName: 'Follow Redirects',
925
+ name: 'followRedirects',
926
+ type: 'boolean',
927
+ default: true,
928
+ description: 'Whether to follow HTTP redirects',
929
+ },
930
+ {
931
+ displayName: 'Ignore SSL Issues',
932
+ name: 'ignoreSslIssues',
933
+ type: 'boolean',
934
+ default: false,
935
+ description: 'Whether to allow the request even when SSL certificate validation fails',
936
+ },
937
+ {
938
+ displayName: 'Include Response Headers and Status',
939
+ name: 'includeHeadersAndStatus',
940
+ type: 'boolean',
941
+ default: false,
942
+ description: 'Whether to return the full response instead of only the body',
943
+ },
944
+ {
945
+ displayName: 'Max Redirects',
946
+ name: 'maxRedirects',
947
+ type: 'number',
948
+ default: 21,
949
+ displayOptions: {
950
+ show: {
951
+ followRedirects: [true],
952
+ },
953
+ },
954
+ description: 'Maximum number of redirects to follow',
955
+ },
956
+ {
957
+ displayName: 'Never Error',
958
+ name: 'neverError',
959
+ type: 'boolean',
960
+ default: false,
961
+ description: 'Whether to return the response even when the status code is not 2xx',
962
+ },
963
+ {
964
+ displayName: 'Proxy',
965
+ name: 'proxy',
966
+ type: 'string',
967
+ default: '',
968
+ placeholder: 'http://proxy.example.com:8080',
969
+ description: 'HTTP proxy to use for this request',
970
+ },
971
+ {
972
+ displayName: 'Timeout',
973
+ name: 'timeout',
974
+ type: 'number',
975
+ default: 30000,
976
+ description: 'Time to wait for the initial response in milliseconds',
977
+ },
978
+ ],
979
+ },
980
+ {
981
+ displayName: 'Options',
982
+ name: POST_REQUEST_OPTIONS_PARAMETER,
983
+ type: 'collection',
984
+ placeholder: 'Add option',
985
+ default: {},
986
+ displayOptions: {
987
+ show: {
988
+ resource: ['post'],
989
+ },
990
+ },
991
+ options: [
992
+ {
993
+ displayName: 'Follow Redirects',
994
+ name: 'followRedirects',
995
+ type: 'boolean',
996
+ default: true,
997
+ description: 'Whether to follow HTTP redirects',
998
+ },
999
+ {
1000
+ displayName: 'Ignore SSL Issues',
1001
+ name: 'ignoreSslIssues',
1002
+ type: 'boolean',
1003
+ default: false,
1004
+ description: 'Whether to allow the request even when SSL certificate validation fails',
1005
+ },
1006
+ {
1007
+ displayName: 'Include Response Headers and Status',
1008
+ name: 'includeHeadersAndStatus',
1009
+ type: 'boolean',
1010
+ default: false,
1011
+ description: 'Whether to return the full response instead of only the body',
1012
+ },
1013
+ {
1014
+ displayName: 'Max Redirects',
1015
+ name: 'maxRedirects',
1016
+ type: 'number',
1017
+ default: 21,
1018
+ displayOptions: {
1019
+ show: {
1020
+ followRedirects: [true],
1021
+ },
1022
+ },
1023
+ description: 'Maximum number of redirects to follow',
1024
+ },
1025
+ {
1026
+ displayName: 'Never Error',
1027
+ name: 'neverError',
1028
+ type: 'boolean',
1029
+ default: false,
1030
+ description: 'Whether to return the response even when the status code is not 2xx',
1031
+ },
1032
+ {
1033
+ displayName: 'Proxy',
1034
+ name: 'proxy',
1035
+ type: 'string',
1036
+ default: '',
1037
+ placeholder: 'http://proxy.example.com:8080',
1038
+ description: 'HTTP proxy to use for this request',
1039
+ },
1040
+ {
1041
+ displayName: 'Timeout',
1042
+ name: 'timeout',
1043
+ type: 'number',
1044
+ default: 30000,
1045
+ description: 'Time to wait for the initial response in milliseconds',
1046
+ },
1047
+ ],
1048
+ },
528
1049
  {
529
1050
  displayName: 'URL',
530
1051
  name: 'customUrl',
@@ -576,6 +1097,42 @@ class AirProcess {
576
1097
  },
577
1098
  description: 'Whether to include a request body',
578
1099
  },
1100
+ {
1101
+ displayName: 'Body Content Type',
1102
+ name: 'customBodyContentType',
1103
+ type: 'options',
1104
+ options: [
1105
+ {
1106
+ name: 'Form URLencoded',
1107
+ value: 'formUrlencoded',
1108
+ },
1109
+ {
1110
+ name: 'Form-Data',
1111
+ value: 'formData',
1112
+ },
1113
+ {
1114
+ name: 'JSON',
1115
+ value: 'json',
1116
+ },
1117
+ {
1118
+ name: 'N8n Binary File',
1119
+ value: 'binaryFile',
1120
+ },
1121
+ {
1122
+ name: 'Raw',
1123
+ value: 'raw',
1124
+ },
1125
+ ],
1126
+ default: 'json',
1127
+ displayOptions: {
1128
+ show: {
1129
+ resource: ['custom'],
1130
+ operation: ['customGet', 'customPost'],
1131
+ customSendBody: [true],
1132
+ },
1133
+ },
1134
+ description: 'Content type to use for the custom POST body',
1135
+ },
579
1136
  {
580
1137
  displayName: 'Body',
581
1138
  name: 'customBody',
@@ -584,11 +1141,194 @@ class AirProcess {
584
1141
  displayOptions: {
585
1142
  show: {
586
1143
  resource: ['custom'],
1144
+ operation: ['customGet', 'customPost'],
587
1145
  customSendBody: [true],
1146
+ customBodyContentType: ['json'],
588
1147
  },
589
1148
  },
590
1149
  description: 'JSON body sent to AirProcess',
591
1150
  },
1151
+ {
1152
+ displayName: 'Body Parameters',
1153
+ name: 'customFormFields',
1154
+ type: 'fixedCollection',
1155
+ typeOptions: {
1156
+ multipleValues: true,
1157
+ },
1158
+ placeholder: 'Add Parameter',
1159
+ default: {
1160
+ parameter: [],
1161
+ },
1162
+ displayOptions: {
1163
+ show: {
1164
+ resource: ['custom'],
1165
+ operation: ['customGet', 'customPost'],
1166
+ customSendBody: [true],
1167
+ customBodyContentType: ['formUrlencoded'],
1168
+ },
1169
+ },
1170
+ options: [
1171
+ {
1172
+ name: 'parameter',
1173
+ displayName: 'Parameter',
1174
+ values: [
1175
+ {
1176
+ displayName: 'Name',
1177
+ name: 'name',
1178
+ type: 'string',
1179
+ default: '',
1180
+ },
1181
+ {
1182
+ displayName: 'Value',
1183
+ name: 'value',
1184
+ type: 'string',
1185
+ default: '',
1186
+ },
1187
+ ],
1188
+ },
1189
+ ],
1190
+ description: 'Parameters to include in the URL-encoded body',
1191
+ },
1192
+ {
1193
+ displayName: 'Body',
1194
+ name: 'customFormDataFields',
1195
+ type: 'fixedCollection',
1196
+ typeOptions: {
1197
+ multipleValues: true,
1198
+ },
1199
+ placeholder: 'Add Body Field',
1200
+ default: {
1201
+ bodyField: [],
1202
+ },
1203
+ displayOptions: {
1204
+ show: {
1205
+ resource: ['custom'],
1206
+ operation: ['customGet', 'customPost'],
1207
+ customSendBody: [true],
1208
+ customBodyContentType: ['formData'],
1209
+ },
1210
+ },
1211
+ options: [
1212
+ {
1213
+ name: 'bodyField',
1214
+ displayName: 'Body Field',
1215
+ values: [
1216
+ {
1217
+ displayName: 'Type',
1218
+ name: 'type',
1219
+ type: 'options',
1220
+ options: [
1221
+ {
1222
+ name: 'Form Data',
1223
+ value: 'formData',
1224
+ },
1225
+ {
1226
+ name: 'N8n Binary File',
1227
+ value: 'binaryFile',
1228
+ },
1229
+ ],
1230
+ default: 'formData',
1231
+ },
1232
+ {
1233
+ displayName: 'Name',
1234
+ name: 'name',
1235
+ type: 'string',
1236
+ default: '',
1237
+ },
1238
+ {
1239
+ displayName: 'Input Data Field Name',
1240
+ name: 'inputDataFieldName',
1241
+ type: 'string',
1242
+ default: 'data',
1243
+ displayOptions: {
1244
+ show: {
1245
+ type: ['binaryFile'],
1246
+ },
1247
+ },
1248
+ description: 'Binary property from the incoming item to attach to the form-data body',
1249
+ },
1250
+ {
1251
+ displayName: 'Value',
1252
+ name: 'value',
1253
+ type: 'string',
1254
+ default: '',
1255
+ displayOptions: {
1256
+ show: {
1257
+ type: ['formData'],
1258
+ },
1259
+ },
1260
+ },
1261
+ ],
1262
+ },
1263
+ ],
1264
+ description: 'Fields to include in the form-data body',
1265
+ },
1266
+ {
1267
+ displayName: 'Input Data Field Name',
1268
+ name: 'customBinaryInputDataFieldName',
1269
+ type: 'string',
1270
+ default: 'data',
1271
+ required: true,
1272
+ displayOptions: {
1273
+ show: {
1274
+ resource: ['custom'],
1275
+ operation: ['customGet', 'customPost'],
1276
+ customSendBody: [true],
1277
+ customBodyContentType: ['binaryFile'],
1278
+ },
1279
+ },
1280
+ description: 'Name of the incoming binary property to send as the request body',
1281
+ },
1282
+ {
1283
+ displayName: 'Content Type',
1284
+ name: 'customBinaryContentType',
1285
+ type: 'string',
1286
+ default: 'application/octet-stream',
1287
+ displayOptions: {
1288
+ show: {
1289
+ resource: ['custom'],
1290
+ operation: ['customGet', 'customPost'],
1291
+ customSendBody: [true],
1292
+ customBodyContentType: ['binaryFile'],
1293
+ },
1294
+ },
1295
+ description: 'Content-Type header to use for the binary body',
1296
+ },
1297
+ {
1298
+ displayName: 'Content Type',
1299
+ name: 'customRawContentType',
1300
+ type: 'string',
1301
+ default: 'text/plain',
1302
+ required: true,
1303
+ displayOptions: {
1304
+ show: {
1305
+ resource: ['custom'],
1306
+ operation: ['customGet', 'customPost'],
1307
+ customSendBody: [true],
1308
+ customBodyContentType: ['raw'],
1309
+ },
1310
+ },
1311
+ description: 'Content-Type header to use for the raw body',
1312
+ },
1313
+ {
1314
+ displayName: 'Body',
1315
+ name: 'customRawBody',
1316
+ type: 'string',
1317
+ typeOptions: {
1318
+ rows: 5,
1319
+ },
1320
+ default: '',
1321
+ required: true,
1322
+ displayOptions: {
1323
+ show: {
1324
+ resource: ['custom'],
1325
+ operation: ['customGet', 'customPost'],
1326
+ customSendBody: [true],
1327
+ customBodyContentType: ['raw'],
1328
+ },
1329
+ },
1330
+ description: 'Raw body content sent to AirProcess',
1331
+ },
592
1332
  {
593
1333
  displayName: 'Model Name or ID',
594
1334
  name: 'modelIdGetOneModel',
@@ -733,6 +1473,41 @@ class AirProcess {
733
1473
  },
734
1474
  description: 'Record identifier used in the path',
735
1475
  },
1476
+ {
1477
+ displayName: 'Body Content Type',
1478
+ name: 'createBodyContentType',
1479
+ type: 'options',
1480
+ options: [
1481
+ {
1482
+ name: 'Form URLencoded',
1483
+ value: 'formUrlencoded',
1484
+ },
1485
+ {
1486
+ name: 'Form-Data',
1487
+ value: 'formData',
1488
+ },
1489
+ {
1490
+ name: 'JSON',
1491
+ value: 'json',
1492
+ },
1493
+ {
1494
+ name: 'N8n Binary File',
1495
+ value: 'binaryFile',
1496
+ },
1497
+ {
1498
+ name: 'Raw',
1499
+ value: 'raw',
1500
+ },
1501
+ ],
1502
+ default: 'json',
1503
+ displayOptions: {
1504
+ show: {
1505
+ resource: ['post'],
1506
+ operation: ['createRecord'],
1507
+ },
1508
+ },
1509
+ description: 'Content type to use for the POST body',
1510
+ },
736
1511
  {
737
1512
  displayName: 'Specify Body',
738
1513
  name: 'createBodyMode',
@@ -752,6 +1527,7 @@ class AirProcess {
752
1527
  show: {
753
1528
  resource: ['post'],
754
1529
  operation: ['createRecord'],
1530
+ createBodyContentType: ['json'],
755
1531
  },
756
1532
  },
757
1533
  description: 'Choose whether to send raw JSON or build the body from fields',
@@ -766,6 +1542,7 @@ class AirProcess {
766
1542
  show: {
767
1543
  resource: ['post'],
768
1544
  operation: ['createRecord'],
1545
+ createBodyContentType: ['json'],
769
1546
  createBodyMode: ['json'],
770
1547
  },
771
1548
  },
@@ -786,6 +1563,7 @@ class AirProcess {
786
1563
  show: {
787
1564
  resource: ['post'],
788
1565
  operation: ['createRecord'],
1566
+ createBodyContentType: ['json'],
789
1567
  createBodyMode: ['fields'],
790
1568
  },
791
1569
  },
@@ -816,6 +1594,113 @@ class AirProcess {
816
1594
  ],
817
1595
  description: 'Build the body by selecting model fields and values',
818
1596
  },
1597
+ {
1598
+ displayName: 'Body Parameters',
1599
+ name: 'createFormFields',
1600
+ type: 'fixedCollection',
1601
+ typeOptions: {
1602
+ multipleValues: true,
1603
+ },
1604
+ placeholder: 'Add Parameter',
1605
+ default: {
1606
+ field: [],
1607
+ },
1608
+ displayOptions: {
1609
+ show: {
1610
+ resource: ['post'],
1611
+ operation: ['createRecord'],
1612
+ createBodyContentType: ['formUrlencoded', 'formData'],
1613
+ },
1614
+ },
1615
+ options: [
1616
+ {
1617
+ name: 'field',
1618
+ displayName: 'Field',
1619
+ values: [
1620
+ {
1621
+ displayName: 'Field Name or ID',
1622
+ name: 'fieldId',
1623
+ type: 'options',
1624
+ typeOptions: {
1625
+ loadOptionsMethod: 'getModelFields',
1626
+ loadOptionsDependsOn: ['modelIdCreate', 'createFormFields.field'],
1627
+ },
1628
+ default: '',
1629
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
1630
+ },
1631
+ {
1632
+ displayName: 'Value',
1633
+ name: 'value',
1634
+ type: 'string',
1635
+ default: '',
1636
+ },
1637
+ ],
1638
+ },
1639
+ ],
1640
+ description: 'Build the body by selecting model fields and values',
1641
+ },
1642
+ {
1643
+ displayName: 'Input Data Field Name',
1644
+ name: 'createBinaryInputDataFieldName',
1645
+ type: 'string',
1646
+ default: 'data',
1647
+ required: true,
1648
+ displayOptions: {
1649
+ show: {
1650
+ resource: ['post'],
1651
+ operation: ['createRecord'],
1652
+ createBodyContentType: ['binaryFile'],
1653
+ },
1654
+ },
1655
+ description: 'Name of the incoming binary property to send as the request body',
1656
+ },
1657
+ {
1658
+ displayName: 'Content Type',
1659
+ name: 'createBinaryContentType',
1660
+ type: 'string',
1661
+ default: 'application/octet-stream',
1662
+ displayOptions: {
1663
+ show: {
1664
+ resource: ['post'],
1665
+ operation: ['createRecord'],
1666
+ createBodyContentType: ['binaryFile'],
1667
+ },
1668
+ },
1669
+ description: 'Content-Type header to use for the binary body',
1670
+ },
1671
+ {
1672
+ displayName: 'Content Type',
1673
+ name: 'createRawContentType',
1674
+ type: 'string',
1675
+ default: 'text/plain',
1676
+ required: true,
1677
+ displayOptions: {
1678
+ show: {
1679
+ resource: ['post'],
1680
+ operation: ['createRecord'],
1681
+ createBodyContentType: ['raw'],
1682
+ },
1683
+ },
1684
+ description: 'Content-Type header to use for the raw body',
1685
+ },
1686
+ {
1687
+ displayName: 'Body',
1688
+ name: 'createRawBody',
1689
+ type: 'string',
1690
+ typeOptions: {
1691
+ rows: 5,
1692
+ },
1693
+ default: '',
1694
+ required: true,
1695
+ displayOptions: {
1696
+ show: {
1697
+ resource: ['post'],
1698
+ operation: ['createRecord'],
1699
+ createBodyContentType: ['raw'],
1700
+ },
1701
+ },
1702
+ description: 'Raw body content sent to AirProcess',
1703
+ },
819
1704
  {
820
1705
  displayName: 'Specify Body',
821
1706
  name: 'updateBodyMode',