n8n-nodes-airprocess 0.1.21 → 0.1.23

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.
@@ -4,13 +4,17 @@ exports.AirProcess = void 0;
4
4
  const n8n_workflow_1 = require("n8n-workflow");
5
5
  const AIRPROCESS_BASE_URL = 'https://app.airprocess.com';
6
6
  const AIRPROCESS_MODELS_URL = `${AIRPROCESS_BASE_URL}/model`;
7
+ const AIRPROCESS_ACTIVE_VIEWS_URL = `${AIRPROCESS_BASE_URL}/command/views/activeForCurrentAccount`;
7
8
  const CUSTOM_URL_EXPRESSION = '={{ $parameter.customUrl.startsWith("http") ? $parameter.customUrl : ($parameter.customUrl.startsWith("/") ? $parameter.customUrl : "/" + $parameter.customUrl) }}';
8
9
  const CUSTOM_BODY_EXPRESSION = '={{ $parameter.customSendBody ? (typeof $parameter.customBody === "string" ? JSON.parse($parameter.customBody) : $parameter.customBody) : undefined }}';
9
10
  const AUTHORIZATION_HEADER_EXPRESSION = '={{ undefined }}';
10
11
  const CUSTOM_HEADERS_EXPRESSION = '={{ $parameter.customSendHeaders ? (typeof $parameter.customHeaders === "string" ? JSON.parse($parameter.customHeaders) : $parameter.customHeaders) : {} }}';
12
+ const GET_REQUEST_OPTIONS_PARAMETER = 'getRequestOptions';
13
+ const POST_REQUEST_OPTIONS_PARAMETER = 'postRequestOptions';
14
+ const CUSTOM_REQUEST_OPTIONS_PARAMETER = 'customRequestOptions';
11
15
  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
- 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 }; })() }}`;
16
+ 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; }, {}); const paginationOptions = $parameter.postRequestOptions ?? {}; return { operation: "search", filterSyntax: "mongo", skip: Number(paginationOptions.skip ?? $parameter.findSkip ?? 0), limit: Number(paginationOptions.limit ?? $parameter.findLimit ?? 10), filter }; })() }}`;
17
+ const GET_PRIVATE_VIEW_DATA_BODY_EXPRESSION = `={{ (() => { const resolveCollectionValue = ${RESOLVE_COLLECTION_VALUE_EXPRESSION}; const body = { modelId: $parameter.modelIdViewData, viewId: $parameter.viewIdViewData }; const fields = (($parameter.viewDataFields && $parameter.viewDataFields.field) ? $parameter.viewDataFields.field : []).map((current) => resolveCollectionValue(current.fieldId)).filter((fieldId) => Boolean(fieldId)); if (fields.length > 0) { body.fields = fields; } if ($parameter.viewDataAddFilter) { const fieldId = resolveCollectionValue($parameter.viewDataFilterFieldId); if (fieldId) { body.filter = { type: "filter", fieldId, operator: resolveCollectionValue($parameter.viewDataFilterOperator), value: resolveCollectionValue($parameter.viewDataFilterValue) }; } } if ($parameter.viewDataAddSort) { const sort = typeof $parameter.viewDataSort === "string" ? JSON.parse($parameter.viewDataSort) : $parameter.viewDataSort; if (sort && (typeof sort !== "object" || Object.keys(sort).length > 0)) { body.sort = sort; } } const paginationOptions = $parameter.postRequestOptions ?? {}; if (paginationOptions.skip !== undefined) { body.skip = Number(paginationOptions.skip); } if (paginationOptions.limit !== undefined) { body.limit = Number(paginationOptions.limit); } return body; })() }}`;
14
18
  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
19
  function toModelOption(item) {
16
20
  var _a, _b, _c, _d;
@@ -93,6 +97,271 @@ function extractSingleFromResponse(response) {
93
97
  }
94
98
  return undefined;
95
99
  }
100
+ function toViewOption(item) {
101
+ if (typeof item.id !== 'string' || item.id.length === 0) {
102
+ return null;
103
+ }
104
+ if (typeof item.name !== 'string' || item.name.length === 0) {
105
+ return null;
106
+ }
107
+ return {
108
+ name: item.name,
109
+ value: item.id,
110
+ };
111
+ }
112
+ function generateUuid() {
113
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (character) => {
114
+ const random = Math.floor(Math.random() * 16);
115
+ const value = character === 'x' ? random : (random & 0x3) | 0x8;
116
+ return value.toString(16);
117
+ });
118
+ }
119
+ function stringifyBodyValue(value) {
120
+ if (value === null || value === undefined) {
121
+ return '';
122
+ }
123
+ if (typeof value === 'object') {
124
+ return JSON.stringify(value);
125
+ }
126
+ return String(value);
127
+ }
128
+ function getCreateFieldPayload(executeFunctions, parameterName) {
129
+ const parameterValue = executeFunctions.getNodeParameter(parameterName, {});
130
+ const selectedFields = Array.isArray(parameterValue.field) ? parameterValue.field : [];
131
+ const payload = {};
132
+ for (const current of selectedFields) {
133
+ const fieldId = typeof current.fieldId === 'string'
134
+ ? current.fieldId.trim()
135
+ : current.fieldId === undefined || current.fieldId === null
136
+ ? ''
137
+ : String(current.fieldId).trim();
138
+ if (fieldId.length === 0) {
139
+ continue;
140
+ }
141
+ payload[fieldId] = current.value;
142
+ }
143
+ return payload;
144
+ }
145
+ function getCreateRecordJsonPayload(executeFunctions) {
146
+ const bodyMode = executeFunctions.getNodeParameter('createBodyMode', 'json');
147
+ if (bodyMode === 'fields') {
148
+ return {
149
+ ...getCreateFieldPayload(executeFunctions, 'createFields'),
150
+ id: generateUuid(),
151
+ };
152
+ }
153
+ const bodyValue = executeFunctions.getNodeParameter('bodyCreate', {});
154
+ const payload = typeof bodyValue === 'string'
155
+ ? JSON.parse(bodyValue)
156
+ : (bodyValue !== null && bodyValue !== void 0 ? bodyValue : {});
157
+ return {
158
+ ...payload,
159
+ id: generateUuid(),
160
+ };
161
+ }
162
+ function getCreateRecordFormPayload(executeFunctions) {
163
+ return {
164
+ ...getCreateFieldPayload(executeFunctions, 'createFormFields'),
165
+ id: generateUuid(),
166
+ };
167
+ }
168
+ function getCustomParameterPayload(executeFunctions) {
169
+ const parameterValue = executeFunctions.getNodeParameter('customFormFields', {});
170
+ const parameters = Array.isArray(parameterValue.parameter) ? parameterValue.parameter : [];
171
+ const payload = {};
172
+ for (const current of parameters) {
173
+ const name = typeof current.name === 'string'
174
+ ? current.name.trim()
175
+ : current.name === undefined || current.name === null
176
+ ? ''
177
+ : String(current.name).trim();
178
+ if (name.length === 0) {
179
+ continue;
180
+ }
181
+ payload[name] = current.value;
182
+ }
183
+ return payload;
184
+ }
185
+ function getCustomFormDataFields(executeFunctions) {
186
+ const parameterValue = executeFunctions.getNodeParameter('customFormDataFields', {});
187
+ const bodyFields = Array.isArray(parameterValue.bodyField) ? parameterValue.bodyField : [];
188
+ return bodyFields
189
+ .map((current) => {
190
+ const name = typeof current.name === 'string'
191
+ ? current.name.trim()
192
+ : current.name === undefined || current.name === null
193
+ ? ''
194
+ : String(current.name).trim();
195
+ const type = current.type === 'binaryFile' ? 'binaryFile' : 'formData';
196
+ const inputDataFieldName = typeof current.inputDataFieldName === 'string'
197
+ ? current.inputDataFieldName.trim()
198
+ : current.inputDataFieldName === undefined || current.inputDataFieldName === null
199
+ ? undefined
200
+ : String(current.inputDataFieldName).trim();
201
+ return {
202
+ inputDataFieldName,
203
+ name,
204
+ type,
205
+ value: current.value,
206
+ };
207
+ })
208
+ .filter((field) => field.name.length > 0);
209
+ }
210
+ async function configureCreateRecordRequest(requestOptions) {
211
+ var _a;
212
+ const bodyContentType = this.getNodeParameter('createBodyContentType', 'json');
213
+ const headers = {
214
+ ...((_a = requestOptions.headers) !== null && _a !== void 0 ? _a : {}),
215
+ };
216
+ switch (bodyContentType) {
217
+ case 'binaryFile': {
218
+ const inputDataFieldName = this.getNodeParameter('createBinaryInputDataFieldName', 'data');
219
+ const contentType = this.getNodeParameter('createBinaryContentType', 'application/octet-stream');
220
+ requestOptions.body = await this.helpers.getBinaryDataBuffer(inputDataFieldName);
221
+ headers['Content-Type'] = contentType;
222
+ break;
223
+ }
224
+ case 'formData': {
225
+ const payload = getCreateRecordFormPayload(this);
226
+ const formData = new FormData();
227
+ for (const [key, value] of Object.entries(payload)) {
228
+ formData.append(key, stringifyBodyValue(value));
229
+ }
230
+ requestOptions.body = formData;
231
+ delete headers['Content-Type'];
232
+ break;
233
+ }
234
+ case 'formUrlencoded': {
235
+ const payload = getCreateRecordFormPayload(this);
236
+ const params = new URLSearchParams();
237
+ for (const [key, value] of Object.entries(payload)) {
238
+ params.append(key, stringifyBodyValue(value));
239
+ }
240
+ requestOptions.body = params;
241
+ headers['Content-Type'] = 'application/x-www-form-urlencoded';
242
+ break;
243
+ }
244
+ case 'raw': {
245
+ const rawBody = this.getNodeParameter('createRawBody', '');
246
+ const rawContentType = this.getNodeParameter('createRawContentType', 'text/plain');
247
+ requestOptions.body = rawBody;
248
+ headers['Content-Type'] = rawContentType;
249
+ break;
250
+ }
251
+ case 'json':
252
+ default: {
253
+ requestOptions.body = getCreateRecordJsonPayload(this);
254
+ headers['Content-Type'] = 'application/json';
255
+ break;
256
+ }
257
+ }
258
+ requestOptions.headers = headers;
259
+ return requestOptions;
260
+ }
261
+ async function configureCustomTypedBodyRequest(requestOptions) {
262
+ var _a;
263
+ const sendBody = this.getNodeParameter('customSendBody', false);
264
+ if (!sendBody) {
265
+ return requestOptions;
266
+ }
267
+ const bodyContentType = this.getNodeParameter('customBodyContentType', 'json');
268
+ const headers = {
269
+ ...((_a = requestOptions.headers) !== null && _a !== void 0 ? _a : {}),
270
+ };
271
+ switch (bodyContentType) {
272
+ case 'binaryFile': {
273
+ const inputDataFieldName = this.getNodeParameter('customBinaryInputDataFieldName', 'data');
274
+ const contentType = this.getNodeParameter('customBinaryContentType', 'application/octet-stream');
275
+ requestOptions.body = await this.helpers.getBinaryDataBuffer(inputDataFieldName);
276
+ headers['Content-Type'] = contentType;
277
+ break;
278
+ }
279
+ case 'formData': {
280
+ const payload = getCustomFormDataFields(this);
281
+ const formData = new FormData();
282
+ for (const field of payload) {
283
+ if (field.type === 'binaryFile') {
284
+ if (!field.inputDataFieldName) {
285
+ continue;
286
+ }
287
+ const binaryMetadata = this.helpers.assertBinaryData(field.inputDataFieldName);
288
+ const buffer = await this.helpers.getBinaryDataBuffer(field.inputDataFieldName);
289
+ const blob = new Blob([buffer], {
290
+ type: binaryMetadata.mimeType || 'application/octet-stream',
291
+ });
292
+ formData.append(field.name, blob, binaryMetadata.fileName || field.inputDataFieldName);
293
+ continue;
294
+ }
295
+ formData.append(field.name, stringifyBodyValue(field.value));
296
+ }
297
+ requestOptions.body = formData;
298
+ delete headers['Content-Type'];
299
+ break;
300
+ }
301
+ case 'formUrlencoded': {
302
+ const payload = getCustomParameterPayload(this);
303
+ const params = new URLSearchParams();
304
+ for (const [key, value] of Object.entries(payload)) {
305
+ params.append(key, stringifyBodyValue(value));
306
+ }
307
+ requestOptions.body = params;
308
+ headers['Content-Type'] = 'application/x-www-form-urlencoded';
309
+ break;
310
+ }
311
+ case 'raw': {
312
+ const rawBody = this.getNodeParameter('customRawBody', '');
313
+ const rawContentType = this.getNodeParameter('customRawContentType', 'text/plain');
314
+ requestOptions.body = rawBody;
315
+ headers['Content-Type'] = rawContentType;
316
+ break;
317
+ }
318
+ case 'json':
319
+ default: {
320
+ const bodyValue = this.getNodeParameter('customBody', {});
321
+ const payload = typeof bodyValue === 'string'
322
+ ? JSON.parse(bodyValue)
323
+ : (bodyValue !== null && bodyValue !== void 0 ? bodyValue : {});
324
+ const operation = this.getNodeParameter('operation', 'customPost');
325
+ const paginationOptions = this.getNodeParameter(CUSTOM_REQUEST_OPTIONS_PARAMETER, {});
326
+ requestOptions.body =
327
+ operation === 'customPost'
328
+ ? {
329
+ ...payload,
330
+ ...(paginationOptions.skip !== undefined
331
+ ? { skip: Number(paginationOptions.skip) }
332
+ : {}),
333
+ ...(paginationOptions.limit !== undefined
334
+ ? { limit: Number(paginationOptions.limit) }
335
+ : {}),
336
+ }
337
+ : payload;
338
+ headers['Content-Type'] = 'application/json';
339
+ break;
340
+ }
341
+ }
342
+ requestOptions.headers = headers;
343
+ return requestOptions;
344
+ }
345
+ function buildHttpNodeLikeRequestOptions(parameterName) {
346
+ return {
347
+ ...(parameterName === CUSTOM_REQUEST_OPTIONS_PARAMETER
348
+ ? {
349
+ qs: {
350
+ skip: `={{ $parameter.${parameterName}.skip ?? undefined }}`,
351
+ limit: `={{ $parameter.${parameterName}.limit ?? undefined }}`,
352
+ },
353
+ }
354
+ : {}),
355
+ encoding: `={{ $parameter.${parameterName}.responseFormat === "file" ? "arraybuffer" : ($parameter.${parameterName}.responseFormat === "json" ? "json" : ($parameter.${parameterName}.responseFormat === "text" ? "text" : undefined)) }}`,
356
+ skipSslCertificateValidation: `={{ $parameter.${parameterName}.ignoreSslIssues ?? false }}`,
357
+ disableFollowRedirect: `={{ $parameter.${parameterName}.followRedirects === false }}`,
358
+ maxRedirects: `={{ $parameter.${parameterName}.followRedirects === false ? undefined : $parameter.${parameterName}.maxRedirects }}`,
359
+ returnFullResponse: `={{ $parameter.${parameterName}.includeHeadersAndStatus ?? false }}`,
360
+ ignoreHttpStatusErrors: `={{ $parameter.${parameterName}.neverError ?? false }}`,
361
+ 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 }; })() }}`,
362
+ timeout: `={{ $parameter.${parameterName}.timeout ?? undefined }}`,
363
+ };
364
+ }
96
365
  function resolveModelId(models, selectedModelId) {
97
366
  var _a;
98
367
  const matchingModel = models.find((model) => model.modelID === selectedModelId || model.modelId === selectedModelId || model.id === selectedModelId);
@@ -109,6 +378,54 @@ async function fetchModels(loadOptions) {
109
378
  });
110
379
  return extractListFromResponse(response);
111
380
  }
381
+ async function fetchActiveViews(loadOptions) {
382
+ const credentials = (await loadOptions.getCredentials('airProcessApi'));
383
+ const token = typeof credentials.token === 'string' ? credentials.token.trim() : '';
384
+ const views = [];
385
+ let cursor;
386
+ for (let page = 0; page < 50; page++) {
387
+ const response = await loadOptions.helpers.httpRequestWithAuthentication.call(loadOptions, 'airProcessApi', {
388
+ method: 'POST',
389
+ url: AIRPROCESS_ACTIVE_VIEWS_URL,
390
+ body: {
391
+ limit: 100,
392
+ ...(cursor ? { cursor } : {}),
393
+ },
394
+ json: true,
395
+ headers: token.length > 0 ? { Authorization: `Bearer ${token}` } : undefined,
396
+ });
397
+ views.push(...extractListFromResponse(response));
398
+ const responseData = extractSingleFromResponse(response);
399
+ cursor =
400
+ (responseData === null || responseData === void 0 ? void 0 : responseData.hasMore) === true && typeof responseData.nextCursor === 'string'
401
+ ? responseData.nextCursor
402
+ : undefined;
403
+ if (!cursor) {
404
+ break;
405
+ }
406
+ }
407
+ return views;
408
+ }
409
+ async function getModelViewOptions(loadOptions) {
410
+ const selectedModelId = loadOptions.getCurrentNodeParameter('modelIdViewData');
411
+ if (!selectedModelId) {
412
+ return [];
413
+ }
414
+ const models = await fetchModels(loadOptions);
415
+ const resolvedModelId = resolveModelId(models, selectedModelId);
416
+ const seen = new Set();
417
+ return (await fetchActiveViews(loadOptions))
418
+ .filter((view) => view.modelId === selectedModelId || view.modelId === resolvedModelId)
419
+ .map(toViewOption)
420
+ .filter((option) => option !== null)
421
+ .filter((option) => {
422
+ if (seen.has(option.value)) {
423
+ return false;
424
+ }
425
+ seen.add(option.value);
426
+ return true;
427
+ });
428
+ }
112
429
  async function getModelFieldOptions(loadOptions, modelIdParameterName, selectedFieldsParameterName) {
113
430
  const modelId = loadOptions.getCurrentNodeParameter(modelIdParameterName);
114
431
  if (!modelId) {
@@ -158,6 +475,12 @@ class AirProcess {
158
475
  async getModelFieldsForUpdate() {
159
476
  return await getModelFieldOptions(this, 'modelIdPatch', 'updateFields.field');
160
477
  },
478
+ async getModelViews() {
479
+ return await getModelViewOptions(this);
480
+ },
481
+ async getModelFieldsForViewData() {
482
+ return await getModelFieldOptions(this, 'modelIdViewData', 'viewDataFields.field');
483
+ },
161
484
  },
162
485
  };
163
486
  this.description = {
@@ -166,7 +489,7 @@ class AirProcess {
166
489
  icon: { light: 'file:../../icons/airprocess.svg', dark: 'file:../../icons/airprocess-dark.svg' },
167
490
  group: ['input'],
168
491
  version: 1,
169
- subtitle: '={{$parameter["resource"] + ": " + ($parameter["modelIdGet"] || $parameter["modelIdCreate"] || $parameter["modelIdFind"] || $parameter["modelIdPatch"] || $parameter["modelIdDelete"] || "")}}',
492
+ subtitle: '={{$parameter["resource"] + ": " + ($parameter["modelIdGet"] || $parameter["modelIdCreate"] || $parameter["modelIdFind"] || $parameter["modelIdViewData"] || $parameter["modelIdPatch"] || $parameter["modelIdDelete"] || "")}}',
170
493
  description: 'Interact with the AirProcess API grouped by HTTP method',
171
494
  defaults: {
172
495
  name: 'AirProcess',
@@ -231,10 +554,11 @@ class AirProcess {
231
554
  routing: {
232
555
  request: {
233
556
  method: 'GET',
234
- url: '=/model/{{$parameter.modelIdGetOneModel}}',
557
+ url: '=/model/{{$parameter.modelIdGetOneModel}}?skip={{$parameter.getRequestOptions.skip ?? 0}}&limit={{$parameter.getRequestOptions.limit ?? 50}}',
235
558
  headers: {
236
559
  Authorization: AUTHORIZATION_HEADER_EXPRESSION,
237
560
  },
561
+ ...buildHttpNodeLikeRequestOptions(GET_REQUEST_OPTIONS_PARAMETER),
238
562
  },
239
563
  },
240
564
  },
@@ -245,10 +569,11 @@ class AirProcess {
245
569
  routing: {
246
570
  request: {
247
571
  method: 'GET',
248
- url: '=/{{$parameter.modelIdGet}}/{{$parameter.recordIdGet}}',
572
+ url: '=/{{$parameter.modelIdGet}}/{{$parameter.recordIdGet}}?skip={{$parameter.getRequestOptions.skip ?? 0}}&limit={{$parameter.getRequestOptions.limit ?? 50}}',
249
573
  headers: {
250
574
  Authorization: AUTHORIZATION_HEADER_EXPRESSION,
251
575
  },
576
+ ...buildHttpNodeLikeRequestOptions(GET_REQUEST_OPTIONS_PARAMETER),
252
577
  },
253
578
  },
254
579
  },
@@ -259,10 +584,11 @@ class AirProcess {
259
584
  routing: {
260
585
  request: {
261
586
  method: 'GET',
262
- url: '/application',
587
+ url: '=/application?skip={{$parameter.getRequestOptions.skip ?? 0}}&limit={{$parameter.getRequestOptions.limit ?? 50}}',
263
588
  headers: {
264
589
  Authorization: AUTHORIZATION_HEADER_EXPRESSION,
265
590
  },
591
+ ...buildHttpNodeLikeRequestOptions(GET_REQUEST_OPTIONS_PARAMETER),
266
592
  },
267
593
  },
268
594
  },
@@ -273,10 +599,11 @@ class AirProcess {
273
599
  routing: {
274
600
  request: {
275
601
  method: 'GET',
276
- url: '/group',
602
+ url: '=/group?skip={{$parameter.getRequestOptions.skip ?? 0}}&limit={{$parameter.getRequestOptions.limit ?? 50}}',
277
603
  headers: {
278
604
  Authorization: AUTHORIZATION_HEADER_EXPRESSION,
279
605
  },
606
+ ...buildHttpNodeLikeRequestOptions(GET_REQUEST_OPTIONS_PARAMETER),
280
607
  },
281
608
  },
282
609
  },
@@ -287,10 +614,11 @@ class AirProcess {
287
614
  routing: {
288
615
  request: {
289
616
  method: 'GET',
290
- url: '/model',
617
+ url: '=/model?skip={{$parameter.getRequestOptions.skip ?? 0}}&limit={{$parameter.getRequestOptions.limit ?? 50}}',
291
618
  headers: {
292
619
  Authorization: AUTHORIZATION_HEADER_EXPRESSION,
293
620
  },
621
+ ...buildHttpNodeLikeRequestOptions(GET_REQUEST_OPTIONS_PARAMETER),
294
622
  },
295
623
  },
296
624
  },
@@ -301,10 +629,11 @@ class AirProcess {
301
629
  routing: {
302
630
  request: {
303
631
  method: 'GET',
304
- url: '=/{{$parameter.modelIdGet}}',
632
+ url: '=/{{$parameter.modelIdGet}}?skip={{$parameter.getRequestOptions.skip ?? 0}}&limit={{$parameter.getRequestOptions.limit ?? 50}}',
305
633
  headers: {
306
634
  Authorization: AUTHORIZATION_HEADER_EXPRESSION,
307
635
  },
636
+ ...buildHttpNodeLikeRequestOptions(GET_REQUEST_OPTIONS_PARAMETER),
308
637
  },
309
638
  },
310
639
  },
@@ -315,10 +644,11 @@ class AirProcess {
315
644
  routing: {
316
645
  request: {
317
646
  method: 'GET',
318
- url: '/account',
647
+ url: '=/account?skip={{$parameter.getRequestOptions.skip ?? 0}}&limit={{$parameter.getRequestOptions.limit ?? 50}}',
319
648
  headers: {
320
649
  Authorization: AUTHORIZATION_HEADER_EXPRESSION,
321
650
  },
651
+ ...buildHttpNodeLikeRequestOptions(GET_REQUEST_OPTIONS_PARAMETER),
322
652
  },
323
653
  },
324
654
  },
@@ -329,10 +659,11 @@ class AirProcess {
329
659
  routing: {
330
660
  request: {
331
661
  method: 'GET',
332
- url: '/workspace',
662
+ url: '=/workspace?skip={{$parameter.getRequestOptions.skip ?? 0}}&limit={{$parameter.getRequestOptions.limit ?? 50}}',
333
663
  headers: {
334
664
  Authorization: AUTHORIZATION_HEADER_EXPRESSION,
335
665
  },
666
+ ...buildHttpNodeLikeRequestOptions(GET_REQUEST_OPTIONS_PARAMETER),
336
667
  },
337
668
  },
338
669
  },
@@ -358,11 +689,14 @@ class AirProcess {
358
689
  request: {
359
690
  method: 'POST',
360
691
  url: '=/{{$parameter.modelIdCreate}}',
361
- body: CREATE_RECORD_BODY_EXPRESSION,
692
+ body: '={{ {} }}',
362
693
  headers: {
363
694
  Authorization: AUTHORIZATION_HEADER_EXPRESSION,
364
- 'Content-Type': 'application/json',
365
695
  },
696
+ ...buildHttpNodeLikeRequestOptions(POST_REQUEST_OPTIONS_PARAMETER),
697
+ },
698
+ send: {
699
+ preSend: [configureCreateRecordRequest],
366
700
  },
367
701
  },
368
702
  },
@@ -379,6 +713,24 @@ class AirProcess {
379
713
  Authorization: AUTHORIZATION_HEADER_EXPRESSION,
380
714
  'Content-Type': 'application/json',
381
715
  },
716
+ ...buildHttpNodeLikeRequestOptions(POST_REQUEST_OPTIONS_PARAMETER),
717
+ },
718
+ },
719
+ },
720
+ {
721
+ name: 'Get Private View Data',
722
+ value: 'getPrivateViewData',
723
+ action: 'Get data from a private view',
724
+ routing: {
725
+ request: {
726
+ method: 'POST',
727
+ url: '/command/views/getViewData',
728
+ body: GET_PRIVATE_VIEW_DATA_BODY_EXPRESSION,
729
+ headers: {
730
+ Authorization: AUTHORIZATION_HEADER_EXPRESSION,
731
+ 'Content-Type': 'application/json',
732
+ },
733
+ ...buildHttpNodeLikeRequestOptions(POST_REQUEST_OPTIONS_PARAMETER),
382
734
  },
383
735
  },
384
736
  },
@@ -491,8 +843,23 @@ class AirProcess {
491
843
  request: {
492
844
  method: 'GET',
493
845
  url: CUSTOM_URL_EXPRESSION,
494
- body: CUSTOM_BODY_EXPRESSION,
846
+ body: '={{ {} }}',
495
847
  headers: CUSTOM_HEADERS_EXPRESSION,
848
+ ...buildHttpNodeLikeRequestOptions(CUSTOM_REQUEST_OPTIONS_PARAMETER),
849
+ },
850
+ send: {
851
+ preSend: [configureCustomTypedBodyRequest],
852
+ },
853
+ output: {
854
+ postReceive: [
855
+ {
856
+ type: 'binaryData',
857
+ enabled: '={{ $parameter.customRequestOptions.responseFormat === "file" }}',
858
+ properties: {
859
+ destinationProperty: '={{ $parameter.customRequestOptions.responseBinaryPropertyName || "data" }}',
860
+ },
861
+ },
862
+ ],
496
863
  },
497
864
  },
498
865
  },
@@ -517,14 +884,325 @@ class AirProcess {
517
884
  request: {
518
885
  method: 'POST',
519
886
  url: CUSTOM_URL_EXPRESSION,
520
- body: CUSTOM_BODY_EXPRESSION,
887
+ body: '={{ {} }}',
521
888
  headers: CUSTOM_HEADERS_EXPRESSION,
889
+ ...buildHttpNodeLikeRequestOptions(CUSTOM_REQUEST_OPTIONS_PARAMETER),
890
+ },
891
+ send: {
892
+ preSend: [configureCustomTypedBodyRequest],
893
+ },
894
+ output: {
895
+ postReceive: [
896
+ {
897
+ type: 'binaryData',
898
+ enabled: '={{ $parameter.customRequestOptions.responseFormat === "file" }}',
899
+ properties: {
900
+ destinationProperty: '={{ $parameter.customRequestOptions.responseBinaryPropertyName || "data" }}',
901
+ },
902
+ },
903
+ ],
522
904
  },
523
905
  },
524
906
  },
525
907
  ],
526
908
  default: 'customGet',
527
909
  },
910
+ {
911
+ displayName: 'Options',
912
+ name: CUSTOM_REQUEST_OPTIONS_PARAMETER,
913
+ type: 'collection',
914
+ placeholder: 'Add option',
915
+ default: {},
916
+ displayOptions: {
917
+ show: {
918
+ resource: ['custom'],
919
+ operation: ['customGet', 'customPost'],
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: 'Limit',
946
+ name: 'limit',
947
+ type: 'number',
948
+ typeOptions: {
949
+ minValue: 1,
950
+ },
951
+ default: 50,
952
+ description: 'Max number of results to return',
953
+ },
954
+ {
955
+ displayName: 'Max Redirects',
956
+ name: 'maxRedirects',
957
+ type: 'number',
958
+ default: 21,
959
+ displayOptions: {
960
+ show: {
961
+ followRedirects: [true],
962
+ },
963
+ },
964
+ description: 'Maximum number of redirects to follow',
965
+ },
966
+ {
967
+ displayName: 'Never Error',
968
+ name: 'neverError',
969
+ type: 'boolean',
970
+ default: false,
971
+ description: 'Whether to return the response even when the status code is not 2xx',
972
+ },
973
+ {
974
+ displayName: 'Proxy',
975
+ name: 'proxy',
976
+ type: 'string',
977
+ default: '',
978
+ placeholder: 'http://proxy.example.com:8080',
979
+ description: 'HTTP proxy to use for this request',
980
+ },
981
+ {
982
+ displayName: 'Response Binary Property',
983
+ name: 'responseBinaryPropertyName',
984
+ type: 'string',
985
+ default: 'data',
986
+ displayOptions: {
987
+ show: {
988
+ responseFormat: ['file'],
989
+ },
990
+ },
991
+ description: 'Name of the binary property where the downloaded file will be stored',
992
+ },
993
+ {
994
+ displayName: 'Response Format',
995
+ name: 'responseFormat',
996
+ type: 'options',
997
+ options: [
998
+ {
999
+ name: 'Autodetect',
1000
+ value: 'autodetect',
1001
+ },
1002
+ {
1003
+ name: 'File',
1004
+ value: 'file',
1005
+ },
1006
+ {
1007
+ name: 'JSON',
1008
+ value: 'json',
1009
+ },
1010
+ {
1011
+ name: 'Text',
1012
+ value: 'text',
1013
+ },
1014
+ ],
1015
+ default: 'autodetect',
1016
+ description: 'How to interpret the response body',
1017
+ },
1018
+ {
1019
+ displayName: 'Skip',
1020
+ name: 'skip',
1021
+ type: 'number',
1022
+ default: 0,
1023
+ description: 'Number of records to skip for pagination',
1024
+ },
1025
+ {
1026
+ displayName: 'Timeout',
1027
+ name: 'timeout',
1028
+ type: 'number',
1029
+ default: 30000,
1030
+ description: 'Time to wait for the initial response in milliseconds',
1031
+ },
1032
+ ],
1033
+ },
1034
+ {
1035
+ displayName: 'Options',
1036
+ name: GET_REQUEST_OPTIONS_PARAMETER,
1037
+ type: 'collection',
1038
+ placeholder: 'Add option',
1039
+ default: {},
1040
+ displayOptions: {
1041
+ show: {
1042
+ resource: ['get'],
1043
+ },
1044
+ },
1045
+ options: [
1046
+ {
1047
+ displayName: 'Follow Redirects',
1048
+ name: 'followRedirects',
1049
+ type: 'boolean',
1050
+ default: true,
1051
+ description: 'Whether to follow HTTP redirects',
1052
+ },
1053
+ {
1054
+ displayName: 'Ignore SSL Issues',
1055
+ name: 'ignoreSslIssues',
1056
+ type: 'boolean',
1057
+ default: false,
1058
+ description: 'Whether to allow the request even when SSL certificate validation fails',
1059
+ },
1060
+ {
1061
+ displayName: 'Include Response Headers and Status',
1062
+ name: 'includeHeadersAndStatus',
1063
+ type: 'boolean',
1064
+ default: false,
1065
+ description: 'Whether to return the full response instead of only the body',
1066
+ },
1067
+ {
1068
+ displayName: 'Limit',
1069
+ name: 'limit',
1070
+ type: 'number',
1071
+ typeOptions: {
1072
+ minValue: 1,
1073
+ },
1074
+ default: 50,
1075
+ description: 'Max number of results to return',
1076
+ },
1077
+ {
1078
+ displayName: 'Max Redirects',
1079
+ name: 'maxRedirects',
1080
+ type: 'number',
1081
+ default: 21,
1082
+ displayOptions: {
1083
+ show: {
1084
+ followRedirects: [true],
1085
+ },
1086
+ },
1087
+ description: 'Maximum number of redirects to follow',
1088
+ },
1089
+ {
1090
+ displayName: 'Never Error',
1091
+ name: 'neverError',
1092
+ type: 'boolean',
1093
+ default: false,
1094
+ description: 'Whether to return the response even when the status code is not 2xx',
1095
+ },
1096
+ {
1097
+ displayName: 'Proxy',
1098
+ name: 'proxy',
1099
+ type: 'string',
1100
+ default: '',
1101
+ placeholder: 'http://proxy.example.com:8080',
1102
+ description: 'HTTP proxy to use for this request',
1103
+ },
1104
+ {
1105
+ displayName: 'Skip',
1106
+ name: 'skip',
1107
+ type: 'number',
1108
+ default: 0,
1109
+ description: 'Number of records to skip for pagination',
1110
+ },
1111
+ {
1112
+ displayName: 'Timeout',
1113
+ name: 'timeout',
1114
+ type: 'number',
1115
+ default: 30000,
1116
+ description: 'Time to wait for the initial response in milliseconds',
1117
+ },
1118
+ ],
1119
+ },
1120
+ {
1121
+ displayName: 'Options',
1122
+ name: POST_REQUEST_OPTIONS_PARAMETER,
1123
+ type: 'collection',
1124
+ placeholder: 'Add option',
1125
+ default: {},
1126
+ displayOptions: {
1127
+ show: {
1128
+ resource: ['post'],
1129
+ },
1130
+ },
1131
+ options: [
1132
+ {
1133
+ displayName: 'Follow Redirects',
1134
+ name: 'followRedirects',
1135
+ type: 'boolean',
1136
+ default: true,
1137
+ description: 'Whether to follow HTTP redirects',
1138
+ },
1139
+ {
1140
+ displayName: 'Ignore SSL Issues',
1141
+ name: 'ignoreSslIssues',
1142
+ type: 'boolean',
1143
+ default: false,
1144
+ description: 'Whether to allow the request even when SSL certificate validation fails',
1145
+ },
1146
+ {
1147
+ displayName: 'Include Response Headers and Status',
1148
+ name: 'includeHeadersAndStatus',
1149
+ type: 'boolean',
1150
+ default: false,
1151
+ description: 'Whether to return the full response instead of only the body',
1152
+ },
1153
+ {
1154
+ displayName: 'Limit',
1155
+ name: 'limit',
1156
+ type: 'number',
1157
+ typeOptions: {
1158
+ minValue: 1,
1159
+ },
1160
+ default: 50,
1161
+ description: 'Max number of results to return',
1162
+ },
1163
+ {
1164
+ displayName: 'Max Redirects',
1165
+ name: 'maxRedirects',
1166
+ type: 'number',
1167
+ default: 21,
1168
+ displayOptions: {
1169
+ show: {
1170
+ followRedirects: [true],
1171
+ },
1172
+ },
1173
+ description: 'Maximum number of redirects to follow',
1174
+ },
1175
+ {
1176
+ displayName: 'Never Error',
1177
+ name: 'neverError',
1178
+ type: 'boolean',
1179
+ default: false,
1180
+ description: 'Whether to return the response even when the status code is not 2xx',
1181
+ },
1182
+ {
1183
+ displayName: 'Proxy',
1184
+ name: 'proxy',
1185
+ type: 'string',
1186
+ default: '',
1187
+ placeholder: 'http://proxy.example.com:8080',
1188
+ description: 'HTTP proxy to use for this request',
1189
+ },
1190
+ {
1191
+ displayName: 'Skip',
1192
+ name: 'skip',
1193
+ type: 'number',
1194
+ default: 0,
1195
+ description: 'Number of records to skip for pagination',
1196
+ },
1197
+ {
1198
+ displayName: 'Timeout',
1199
+ name: 'timeout',
1200
+ type: 'number',
1201
+ default: 30000,
1202
+ description: 'Time to wait for the initial response in milliseconds',
1203
+ },
1204
+ ],
1205
+ },
528
1206
  {
529
1207
  displayName: 'URL',
530
1208
  name: 'customUrl',
@@ -577,48 +1255,267 @@ class AirProcess {
577
1255
  description: 'Whether to include a request body',
578
1256
  },
579
1257
  {
580
- displayName: 'Body',
581
- name: 'customBody',
582
- type: 'json',
583
- default: '{}',
1258
+ displayName: 'Body Content Type',
1259
+ name: 'customBodyContentType',
1260
+ type: 'options',
1261
+ options: [
1262
+ {
1263
+ name: 'Form URLencoded',
1264
+ value: 'formUrlencoded',
1265
+ },
1266
+ {
1267
+ name: 'Form-Data',
1268
+ value: 'formData',
1269
+ },
1270
+ {
1271
+ name: 'JSON',
1272
+ value: 'json',
1273
+ },
1274
+ {
1275
+ name: 'N8n Binary File',
1276
+ value: 'binaryFile',
1277
+ },
1278
+ {
1279
+ name: 'Raw',
1280
+ value: 'raw',
1281
+ },
1282
+ ],
1283
+ default: 'json',
584
1284
  displayOptions: {
585
1285
  show: {
586
1286
  resource: ['custom'],
1287
+ operation: ['customGet', 'customPost'],
587
1288
  customSendBody: [true],
588
1289
  },
589
1290
  },
590
- description: 'JSON body sent to AirProcess',
1291
+ description: 'Content type to use for the custom POST body',
591
1292
  },
592
1293
  {
593
- displayName: 'Model Name or ID',
594
- name: 'modelIdGetOneModel',
595
- type: 'options',
596
- required: true,
597
- typeOptions: {
598
- loadOptionsMethod: 'getModels',
599
- },
600
- default: '',
1294
+ displayName: 'Body',
1295
+ name: 'customBody',
1296
+ type: 'json',
1297
+ default: '{}',
601
1298
  displayOptions: {
602
1299
  show: {
603
- resource: ['get'],
604
- operation: ['findOneModel'],
1300
+ resource: ['custom'],
1301
+ operation: ['customGet', 'customPost'],
1302
+ customSendBody: [true],
1303
+ customBodyContentType: ['json'],
605
1304
  },
606
1305
  },
607
- description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
1306
+ description: 'JSON body sent to AirProcess',
608
1307
  },
609
1308
  {
610
- displayName: 'Model Name or ID',
611
- name: 'modelIdGet',
612
- type: 'options',
613
- required: true,
1309
+ displayName: 'Body Parameters',
1310
+ name: 'customFormFields',
1311
+ type: 'fixedCollection',
614
1312
  typeOptions: {
615
- loadOptionsMethod: 'getModels',
1313
+ multipleValues: true,
1314
+ },
1315
+ placeholder: 'Add Parameter',
1316
+ default: {
1317
+ parameter: [],
616
1318
  },
617
- default: '',
618
1319
  displayOptions: {
619
1320
  show: {
620
- resource: ['get'],
621
- operation: ['getRecord', 'getRecords'],
1321
+ resource: ['custom'],
1322
+ operation: ['customGet', 'customPost'],
1323
+ customSendBody: [true],
1324
+ customBodyContentType: ['formUrlencoded'],
1325
+ },
1326
+ },
1327
+ options: [
1328
+ {
1329
+ name: 'parameter',
1330
+ displayName: 'Parameter',
1331
+ values: [
1332
+ {
1333
+ displayName: 'Name',
1334
+ name: 'name',
1335
+ type: 'string',
1336
+ default: '',
1337
+ },
1338
+ {
1339
+ displayName: 'Value',
1340
+ name: 'value',
1341
+ type: 'string',
1342
+ default: '',
1343
+ },
1344
+ ],
1345
+ },
1346
+ ],
1347
+ description: 'Parameters to include in the URL-encoded body',
1348
+ },
1349
+ {
1350
+ displayName: 'Body',
1351
+ name: 'customFormDataFields',
1352
+ type: 'fixedCollection',
1353
+ typeOptions: {
1354
+ multipleValues: true,
1355
+ },
1356
+ placeholder: 'Add Body Field',
1357
+ default: {
1358
+ bodyField: [],
1359
+ },
1360
+ displayOptions: {
1361
+ show: {
1362
+ resource: ['custom'],
1363
+ operation: ['customGet', 'customPost'],
1364
+ customSendBody: [true],
1365
+ customBodyContentType: ['formData'],
1366
+ },
1367
+ },
1368
+ options: [
1369
+ {
1370
+ name: 'bodyField',
1371
+ displayName: 'Body Field',
1372
+ values: [
1373
+ {
1374
+ displayName: 'Type',
1375
+ name: 'type',
1376
+ type: 'options',
1377
+ options: [
1378
+ {
1379
+ name: 'Form Data',
1380
+ value: 'formData',
1381
+ },
1382
+ {
1383
+ name: 'N8n Binary File',
1384
+ value: 'binaryFile',
1385
+ },
1386
+ ],
1387
+ default: 'formData',
1388
+ },
1389
+ {
1390
+ displayName: 'Name',
1391
+ name: 'name',
1392
+ type: 'string',
1393
+ default: '',
1394
+ },
1395
+ {
1396
+ displayName: 'Input Data Field Name',
1397
+ name: 'inputDataFieldName',
1398
+ type: 'string',
1399
+ default: 'data',
1400
+ displayOptions: {
1401
+ show: {
1402
+ type: ['binaryFile'],
1403
+ },
1404
+ },
1405
+ description: 'Binary property from the incoming item to attach to the form-data body',
1406
+ },
1407
+ {
1408
+ displayName: 'Value',
1409
+ name: 'value',
1410
+ type: 'string',
1411
+ default: '',
1412
+ displayOptions: {
1413
+ show: {
1414
+ type: ['formData'],
1415
+ },
1416
+ },
1417
+ },
1418
+ ],
1419
+ },
1420
+ ],
1421
+ description: 'Fields to include in the form-data body',
1422
+ },
1423
+ {
1424
+ displayName: 'Input Data Field Name',
1425
+ name: 'customBinaryInputDataFieldName',
1426
+ type: 'string',
1427
+ default: 'data',
1428
+ required: true,
1429
+ displayOptions: {
1430
+ show: {
1431
+ resource: ['custom'],
1432
+ operation: ['customGet', 'customPost'],
1433
+ customSendBody: [true],
1434
+ customBodyContentType: ['binaryFile'],
1435
+ },
1436
+ },
1437
+ description: 'Name of the incoming binary property to send as the request body',
1438
+ },
1439
+ {
1440
+ displayName: 'Content Type',
1441
+ name: 'customBinaryContentType',
1442
+ type: 'string',
1443
+ default: 'application/octet-stream',
1444
+ displayOptions: {
1445
+ show: {
1446
+ resource: ['custom'],
1447
+ operation: ['customGet', 'customPost'],
1448
+ customSendBody: [true],
1449
+ customBodyContentType: ['binaryFile'],
1450
+ },
1451
+ },
1452
+ description: 'Content-Type header to use for the binary body',
1453
+ },
1454
+ {
1455
+ displayName: 'Content Type',
1456
+ name: 'customRawContentType',
1457
+ type: 'string',
1458
+ default: 'text/plain',
1459
+ required: true,
1460
+ displayOptions: {
1461
+ show: {
1462
+ resource: ['custom'],
1463
+ operation: ['customGet', 'customPost'],
1464
+ customSendBody: [true],
1465
+ customBodyContentType: ['raw'],
1466
+ },
1467
+ },
1468
+ description: 'Content-Type header to use for the raw body',
1469
+ },
1470
+ {
1471
+ displayName: 'Body',
1472
+ name: 'customRawBody',
1473
+ type: 'string',
1474
+ typeOptions: {
1475
+ rows: 5,
1476
+ },
1477
+ default: '',
1478
+ required: true,
1479
+ displayOptions: {
1480
+ show: {
1481
+ resource: ['custom'],
1482
+ operation: ['customGet', 'customPost'],
1483
+ customSendBody: [true],
1484
+ customBodyContentType: ['raw'],
1485
+ },
1486
+ },
1487
+ description: 'Raw body content sent to AirProcess',
1488
+ },
1489
+ {
1490
+ displayName: 'Model Name or ID',
1491
+ name: 'modelIdGetOneModel',
1492
+ type: 'options',
1493
+ required: true,
1494
+ typeOptions: {
1495
+ loadOptionsMethod: 'getModels',
1496
+ },
1497
+ default: '',
1498
+ displayOptions: {
1499
+ show: {
1500
+ resource: ['get'],
1501
+ operation: ['findOneModel'],
1502
+ },
1503
+ },
1504
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
1505
+ },
1506
+ {
1507
+ displayName: 'Model Name or ID',
1508
+ name: 'modelIdGet',
1509
+ type: 'options',
1510
+ required: true,
1511
+ typeOptions: {
1512
+ loadOptionsMethod: 'getModels',
1513
+ },
1514
+ default: '',
1515
+ displayOptions: {
1516
+ show: {
1517
+ resource: ['get'],
1518
+ operation: ['getRecord', 'getRecords'],
622
1519
  },
623
1520
  },
624
1521
  description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
@@ -674,6 +1571,41 @@ class AirProcess {
674
1571
  },
675
1572
  description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
676
1573
  },
1574
+ {
1575
+ displayName: 'Model Name or ID',
1576
+ name: 'modelIdViewData',
1577
+ type: 'options',
1578
+ required: true,
1579
+ typeOptions: {
1580
+ loadOptionsMethod: 'getModels',
1581
+ },
1582
+ default: '',
1583
+ displayOptions: {
1584
+ show: {
1585
+ resource: ['post'],
1586
+ operation: ['getPrivateViewData'],
1587
+ },
1588
+ },
1589
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
1590
+ },
1591
+ {
1592
+ displayName: 'Private View Name or ID',
1593
+ name: 'viewIdViewData',
1594
+ type: 'options',
1595
+ required: true,
1596
+ typeOptions: {
1597
+ loadOptionsMethod: 'getModelViews',
1598
+ loadOptionsDependsOn: ['modelIdViewData'],
1599
+ },
1600
+ default: '',
1601
+ displayOptions: {
1602
+ show: {
1603
+ resource: ['post'],
1604
+ operation: ['getPrivateViewData'],
1605
+ },
1606
+ },
1607
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
1608
+ },
677
1609
  {
678
1610
  displayName: 'Model Name or ID',
679
1611
  name: 'modelIdDelete',
@@ -733,6 +1665,41 @@ class AirProcess {
733
1665
  },
734
1666
  description: 'Record identifier used in the path',
735
1667
  },
1668
+ {
1669
+ displayName: 'Body Content Type',
1670
+ name: 'createBodyContentType',
1671
+ type: 'options',
1672
+ options: [
1673
+ {
1674
+ name: 'Form URLencoded',
1675
+ value: 'formUrlencoded',
1676
+ },
1677
+ {
1678
+ name: 'Form-Data',
1679
+ value: 'formData',
1680
+ },
1681
+ {
1682
+ name: 'JSON',
1683
+ value: 'json',
1684
+ },
1685
+ {
1686
+ name: 'N8n Binary File',
1687
+ value: 'binaryFile',
1688
+ },
1689
+ {
1690
+ name: 'Raw',
1691
+ value: 'raw',
1692
+ },
1693
+ ],
1694
+ default: 'json',
1695
+ displayOptions: {
1696
+ show: {
1697
+ resource: ['post'],
1698
+ operation: ['createRecord'],
1699
+ },
1700
+ },
1701
+ description: 'Content type to use for the POST body',
1702
+ },
736
1703
  {
737
1704
  displayName: 'Specify Body',
738
1705
  name: 'createBodyMode',
@@ -752,6 +1719,7 @@ class AirProcess {
752
1719
  show: {
753
1720
  resource: ['post'],
754
1721
  operation: ['createRecord'],
1722
+ createBodyContentType: ['json'],
755
1723
  },
756
1724
  },
757
1725
  description: 'Choose whether to send raw JSON or build the body from fields',
@@ -766,6 +1734,7 @@ class AirProcess {
766
1734
  show: {
767
1735
  resource: ['post'],
768
1736
  operation: ['createRecord'],
1737
+ createBodyContentType: ['json'],
769
1738
  createBodyMode: ['json'],
770
1739
  },
771
1740
  },
@@ -786,6 +1755,7 @@ class AirProcess {
786
1755
  show: {
787
1756
  resource: ['post'],
788
1757
  operation: ['createRecord'],
1758
+ createBodyContentType: ['json'],
789
1759
  createBodyMode: ['fields'],
790
1760
  },
791
1761
  },
@@ -816,6 +1786,113 @@ class AirProcess {
816
1786
  ],
817
1787
  description: 'Build the body by selecting model fields and values',
818
1788
  },
1789
+ {
1790
+ displayName: 'Body Parameters',
1791
+ name: 'createFormFields',
1792
+ type: 'fixedCollection',
1793
+ typeOptions: {
1794
+ multipleValues: true,
1795
+ },
1796
+ placeholder: 'Add Parameter',
1797
+ default: {
1798
+ field: [],
1799
+ },
1800
+ displayOptions: {
1801
+ show: {
1802
+ resource: ['post'],
1803
+ operation: ['createRecord'],
1804
+ createBodyContentType: ['formUrlencoded', 'formData'],
1805
+ },
1806
+ },
1807
+ options: [
1808
+ {
1809
+ name: 'field',
1810
+ displayName: 'Field',
1811
+ values: [
1812
+ {
1813
+ displayName: 'Field Name or ID',
1814
+ name: 'fieldId',
1815
+ type: 'options',
1816
+ typeOptions: {
1817
+ loadOptionsMethod: 'getModelFields',
1818
+ loadOptionsDependsOn: ['modelIdCreate', 'createFormFields.field'],
1819
+ },
1820
+ default: '',
1821
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
1822
+ },
1823
+ {
1824
+ displayName: 'Value',
1825
+ name: 'value',
1826
+ type: 'string',
1827
+ default: '',
1828
+ },
1829
+ ],
1830
+ },
1831
+ ],
1832
+ description: 'Build the body by selecting model fields and values',
1833
+ },
1834
+ {
1835
+ displayName: 'Input Data Field Name',
1836
+ name: 'createBinaryInputDataFieldName',
1837
+ type: 'string',
1838
+ default: 'data',
1839
+ required: true,
1840
+ displayOptions: {
1841
+ show: {
1842
+ resource: ['post'],
1843
+ operation: ['createRecord'],
1844
+ createBodyContentType: ['binaryFile'],
1845
+ },
1846
+ },
1847
+ description: 'Name of the incoming binary property to send as the request body',
1848
+ },
1849
+ {
1850
+ displayName: 'Content Type',
1851
+ name: 'createBinaryContentType',
1852
+ type: 'string',
1853
+ default: 'application/octet-stream',
1854
+ displayOptions: {
1855
+ show: {
1856
+ resource: ['post'],
1857
+ operation: ['createRecord'],
1858
+ createBodyContentType: ['binaryFile'],
1859
+ },
1860
+ },
1861
+ description: 'Content-Type header to use for the binary body',
1862
+ },
1863
+ {
1864
+ displayName: 'Content Type',
1865
+ name: 'createRawContentType',
1866
+ type: 'string',
1867
+ default: 'text/plain',
1868
+ required: true,
1869
+ displayOptions: {
1870
+ show: {
1871
+ resource: ['post'],
1872
+ operation: ['createRecord'],
1873
+ createBodyContentType: ['raw'],
1874
+ },
1875
+ },
1876
+ description: 'Content-Type header to use for the raw body',
1877
+ },
1878
+ {
1879
+ displayName: 'Body',
1880
+ name: 'createRawBody',
1881
+ type: 'string',
1882
+ typeOptions: {
1883
+ rows: 5,
1884
+ },
1885
+ default: '',
1886
+ required: true,
1887
+ displayOptions: {
1888
+ show: {
1889
+ resource: ['post'],
1890
+ operation: ['createRecord'],
1891
+ createBodyContentType: ['raw'],
1892
+ },
1893
+ },
1894
+ description: 'Raw body content sent to AirProcess',
1895
+ },
819
1896
  {
820
1897
  displayName: 'Specify Body',
821
1898
  name: 'updateBodyMode',
@@ -1009,6 +2086,134 @@ class AirProcess {
1009
2086
  ],
1010
2087
  description: 'Build the mongo filter by selecting model fields and values',
1011
2088
  },
2089
+ {
2090
+ displayName: 'Fields',
2091
+ name: 'viewDataFields',
2092
+ type: 'fixedCollection',
2093
+ typeOptions: {
2094
+ multipleValues: true,
2095
+ },
2096
+ placeholder: 'Add Field',
2097
+ default: {
2098
+ field: [],
2099
+ },
2100
+ displayOptions: {
2101
+ show: {
2102
+ resource: ['post'],
2103
+ operation: ['getPrivateViewData'],
2104
+ },
2105
+ },
2106
+ options: [
2107
+ {
2108
+ name: 'field',
2109
+ displayName: 'Field',
2110
+ values: [
2111
+ {
2112
+ displayName: 'Field Name or ID',
2113
+ name: 'fieldId',
2114
+ type: 'options',
2115
+ typeOptions: {
2116
+ loadOptionsMethod: 'getModelFieldsForViewData',
2117
+ loadOptionsDependsOn: ['modelIdViewData', 'viewDataFields.field'],
2118
+ },
2119
+ default: '',
2120
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
2121
+ },
2122
+ ],
2123
+ },
2124
+ ],
2125
+ description: 'Optional fields to return. Leave empty to let the private view use its default fields.',
2126
+ },
2127
+ {
2128
+ displayName: 'Add Filter',
2129
+ name: 'viewDataAddFilter',
2130
+ type: 'boolean',
2131
+ default: false,
2132
+ displayOptions: {
2133
+ show: {
2134
+ resource: ['post'],
2135
+ operation: ['getPrivateViewData'],
2136
+ },
2137
+ },
2138
+ description: 'Whether to filter the private-view data',
2139
+ },
2140
+ {
2141
+ displayName: 'Filter Field Name or ID',
2142
+ name: 'viewDataFilterFieldId',
2143
+ type: 'options',
2144
+ required: true,
2145
+ typeOptions: {
2146
+ loadOptionsMethod: 'getModelFieldsForViewData',
2147
+ loadOptionsDependsOn: ['modelIdViewData'],
2148
+ },
2149
+ default: '',
2150
+ displayOptions: {
2151
+ show: {
2152
+ resource: ['post'],
2153
+ operation: ['getPrivateViewData'],
2154
+ viewDataAddFilter: [true],
2155
+ },
2156
+ },
2157
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
2158
+ },
2159
+ {
2160
+ displayName: 'Filter Operator',
2161
+ name: 'viewDataFilterOperator',
2162
+ type: 'string',
2163
+ required: true,
2164
+ default: '=',
2165
+ displayOptions: {
2166
+ show: {
2167
+ resource: ['post'],
2168
+ operation: ['getPrivateViewData'],
2169
+ viewDataAddFilter: [true],
2170
+ },
2171
+ },
2172
+ description: 'AirProcess filter operator, for example =, !=, >, or contains',
2173
+ },
2174
+ {
2175
+ displayName: 'Filter Value',
2176
+ name: 'viewDataFilterValue',
2177
+ type: 'string',
2178
+ required: true,
2179
+ default: '',
2180
+ displayOptions: {
2181
+ show: {
2182
+ resource: ['post'],
2183
+ operation: ['getPrivateViewData'],
2184
+ viewDataAddFilter: [true],
2185
+ },
2186
+ },
2187
+ description: 'Value compared by the filter',
2188
+ },
2189
+ {
2190
+ displayName: 'Add Sort',
2191
+ name: 'viewDataAddSort',
2192
+ type: 'boolean',
2193
+ default: false,
2194
+ displayOptions: {
2195
+ show: {
2196
+ resource: ['post'],
2197
+ operation: ['getPrivateViewData'],
2198
+ },
2199
+ },
2200
+ description: 'Whether to send a sort object to AirProcess',
2201
+ },
2202
+ {
2203
+ displayName: 'Sort (JSON)',
2204
+ name: 'viewDataSort',
2205
+ type: 'json',
2206
+ required: true,
2207
+ default: '{\n "fieldId": "example",\n "direction": "asc"\n}',
2208
+ displayOptions: {
2209
+ show: {
2210
+ resource: ['post'],
2211
+ operation: ['getPrivateViewData'],
2212
+ viewDataAddSort: [true],
2213
+ },
2214
+ },
2215
+ description: 'Optional sort object sent in the "sort" property. Use the format expected by your AirProcess view.',
2216
+ },
1012
2217
  ],
1013
2218
  };
1014
2219
  }