n8n-nodes-mautic-advanced 0.2.0 → 0.2.5

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.
@@ -31,6 +31,12 @@ exports.contactOperations = [
31
31
  description: 'Delete a contact',
32
32
  action: 'Delete a contact',
33
33
  },
34
+ {
35
+ name: 'Delete Batch',
36
+ value: 'deleteBatch',
37
+ description: 'Delete multiple contacts in one operation',
38
+ action: 'Delete multiple contacts',
39
+ },
34
40
  {
35
41
  name: 'Edit Contact Points',
36
42
  value: 'editContactPoint',
@@ -1315,6 +1321,46 @@ exports.contactFields = [
1315
1321
  default: '',
1316
1322
  },
1317
1323
  /* -------------------------------------------------------------------------- */
1324
+ /* contact:deleteBatch */
1325
+ /* -------------------------------------------------------------------------- */
1326
+ {
1327
+ displayName: 'Contact IDs',
1328
+ name: 'contactIds',
1329
+ type: 'string',
1330
+ required: false,
1331
+ displayOptions: {
1332
+ show: {
1333
+ resource: ['contact'],
1334
+ operation: ['deleteBatch'],
1335
+ },
1336
+ },
1337
+ default: '',
1338
+ placeholder: '1,2,3,4,5',
1339
+ description: 'Comma-separated list of contact IDs to delete (e.g., "1,2,3,4,5"). If left empty, all input items\' contactId fields will be used for batch deletion.',
1340
+ },
1341
+ {
1342
+ displayName: 'Options',
1343
+ name: 'options',
1344
+ type: 'collection',
1345
+ displayOptions: {
1346
+ show: {
1347
+ resource: ['contact'],
1348
+ operation: ['deleteBatch'],
1349
+ },
1350
+ },
1351
+ placeholder: 'Add option',
1352
+ default: {},
1353
+ options: [
1354
+ {
1355
+ displayName: 'RAW Data',
1356
+ name: 'rawData',
1357
+ type: 'boolean',
1358
+ default: true,
1359
+ description: 'Whether to return the raw response data from the API or just a success summary',
1360
+ },
1361
+ ],
1362
+ },
1363
+ /* -------------------------------------------------------------------------- */
1318
1364
  /* contact:all */
1319
1365
  /* -------------------------------------------------------------------------- */
1320
1366
  {
@@ -1326,7 +1372,7 @@ exports.contactFields = [
1326
1372
  resource: ['contact'],
1327
1373
  },
1328
1374
  hide: {
1329
- operation: ['sendEmail', 'editDoNotContactList', 'editContactPoint'],
1375
+ operation: ['sendEmail', 'editDoNotContactList', 'editContactPoint', 'deleteBatch'],
1330
1376
  },
1331
1377
  },
1332
1378
  placeholder: 'Add option',
@@ -43,26 +43,46 @@ exports.mauticApiRequest = mauticApiRequest;
43
43
  * Make an API request to paginated mautic endpoint
44
44
  * and return all results
45
45
  */
46
+ // Optional: Slightly improved error handling
46
47
  async function mauticApiRequestAllItems(propertyName, method, endpoint, body = {}, query = {}, maxResults) {
47
48
  const returnData = [];
48
49
  let responseData;
49
50
  query.limit = 30;
50
51
  query.start = 0;
51
- // Removed unused 'page' variable
52
- do {
53
- responseData = await mauticApiRequest.call(this, method, endpoint, body, query);
54
- const values = Object.values(responseData[propertyName]);
55
- if (maxResults !== undefined && returnData.length + values.length > maxResults) {
56
- const needed = maxResults - returnData.length;
57
- returnData.push(...values.slice(0, needed));
58
- break;
52
+ while (true) {
53
+ try {
54
+ responseData = await mauticApiRequest.call(this, method, endpoint, body, query);
55
+ if (responseData.errors) {
56
+ throw new n8n_workflow_1.NodeApiError(this.getNode(), responseData);
57
+ }
58
+ const pageItems = responseData[propertyName]
59
+ ? Object.values(responseData[propertyName])
60
+ : [];
61
+ if (!pageItems.length) {
62
+ break;
63
+ }
64
+ if (maxResults !== undefined && returnData.length + pageItems.length > maxResults) {
65
+ const needed = maxResults - returnData.length;
66
+ returnData.push(...pageItems.slice(0, needed));
67
+ break;
68
+ }
69
+ else {
70
+ returnData.push(...pageItems);
71
+ }
72
+ query.start = Number(query.start) + pageItems.length;
73
+ // If less than limit returned, no more data
74
+ if (pageItems.length < Number(query.limit)) {
75
+ break;
76
+ }
59
77
  }
60
- else {
61
- returnData.push(...values);
78
+ catch (error) {
79
+ // Optional: Only wrap non-NodeApiError errors
80
+ if (error instanceof n8n_workflow_1.NodeApiError) {
81
+ throw error;
82
+ }
83
+ throw new n8n_workflow_1.NodeApiError(this.getNode(), error);
62
84
  }
63
- query.start += query.limit;
64
- } while ((responseData.total !== undefined && returnData.length - parseInt(responseData.total, 10) < 0) &&
65
- (maxResults === undefined || returnData.length < maxResults));
85
+ }
66
86
  return returnData;
67
87
  }
68
88
  exports.mauticApiRequestAllItems = mauticApiRequestAllItems;
@@ -12,13 +12,14 @@ const ContactDescription_1 = require("./ContactDescription");
12
12
  const ContactSegmentDescription_1 = require("./ContactSegmentDescription");
13
13
  const GenericFunctions_1 = require("./GenericFunctions");
14
14
  const SegmentEmailDescription_1 = require("./SegmentEmailDescription");
15
+ const SegmentDescription_1 = require("./SegmentDescription");
15
16
  const TagDescription_1 = require("./TagDescription");
16
17
  class MauticAdvanced {
17
18
  constructor() {
18
19
  this.description = {
19
20
  displayName: 'Mautic Advanced',
20
21
  name: 'mauticAdvanced',
21
- icon: 'file:MauticAdvanced.svg',
22
+ icon: 'file:mauticadvanced.svg',
22
23
  group: ['output'],
23
24
  version: 1,
24
25
  subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
@@ -107,6 +108,11 @@ class MauticAdvanced {
107
108
  value: 'contactSegment',
108
109
  description: 'Add/remove contacts to/from a segment',
109
110
  },
111
+ {
112
+ name: 'Segment',
113
+ value: 'segment',
114
+ description: 'Create, update, and retrieve segments',
115
+ },
110
116
  {
111
117
  name: 'Segment Email',
112
118
  value: 'segmentEmail',
@@ -138,6 +144,8 @@ class MauticAdvanced {
138
144
  ...TagDescription_1.tagFields,
139
145
  ...CategoryDescription_1.categoryOperations,
140
146
  ...CategoryDescription_1.categoryFields,
147
+ ...SegmentDescription_1.segmentOperations,
148
+ ...SegmentDescription_1.segmentFields,
141
149
  ],
142
150
  };
143
151
  this.methods = {
@@ -226,7 +234,7 @@ class MauticAdvanced {
226
234
  // select them easily
227
235
  async getSegments() {
228
236
  const returnData = [];
229
- const segments = await GenericFunctions_1.mauticApiRequestAllItems.call(this, 'lists', 'GET', '/segments');
237
+ const segments = await GenericFunctions_1.mauticApiRequestAllItems.call(this, 'segments', 'GET', '/segments');
230
238
  for (const segment of segments) {
231
239
  returnData.push({
232
240
  name: segment.name,
@@ -302,6 +310,48 @@ class MauticAdvanced {
302
310
  let responseData;
303
311
  const resource = this.getNodeParameter('resource', 0);
304
312
  const operation = this.getNodeParameter('operation', 0);
313
+ // Handle batch operations that process all items together
314
+ if (resource === 'contact' && operation === 'deleteBatch') {
315
+ // Only process once for all items
316
+ const options = this.getNodeParameter('options', 0, {});
317
+ let contactIds = this.getNodeParameter('contactIds', 0, '');
318
+ if (!contactIds) {
319
+ // Fallback: collect from all input items
320
+ const ids = items
321
+ .map((item) => item.json.id)
322
+ .filter((id) => id !== undefined && id !== null && id !== '')
323
+ .map((id) => String(id));
324
+ contactIds = ids.join(',');
325
+ }
326
+ if (!contactIds) {
327
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No contact IDs provided or found in input items.');
328
+ }
329
+ try {
330
+ responseData = await GenericFunctions_1.mauticApiRequest.call(this, 'DELETE', '/contacts/batch/delete', {}, { ids: contactIds });
331
+ if (options.rawData === false) {
332
+ // Return simplified response
333
+ responseData = {
334
+ success: true,
335
+ deletedIds: contactIds.split(','),
336
+ message: `Successfully deleted ${contactIds.split(',').length} contacts.`,
337
+ };
338
+ }
339
+ }
340
+ catch (error) {
341
+ if (error instanceof n8n_workflow_1.NodeApiError && error.httpCode === '404') {
342
+ responseData = {
343
+ success: true,
344
+ deletedIds: contactIds.split(','),
345
+ message: 'Some contacts were already deleted or not found.',
346
+ };
347
+ }
348
+ else {
349
+ throw error;
350
+ }
351
+ }
352
+ // Return as a single output item
353
+ return [this.helpers.returnJsonArray([responseData])];
354
+ }
305
355
  for (let i = 0; i < length; i++) {
306
356
  qs = {};
307
357
  try {
@@ -339,6 +389,13 @@ class MauticAdvanced {
339
389
  const returnAll = this.getNodeParameter('returnAll', i);
340
390
  const options = this.getNodeParameter('options', i);
341
391
  qs = { ...options };
392
+ // Patch: enforce default sort order by id ascending if not set by user
393
+ if (!qs.orderBy) {
394
+ qs.orderBy = 'id';
395
+ }
396
+ if (!qs.orderByDir) {
397
+ qs.orderByDir = 'asc';
398
+ }
342
399
  if (returnAll) {
343
400
  responseData = await GenericFunctions_1.mauticApiRequestAllItems.call(this, 'campaigns', 'GET', '/campaigns', {}, qs);
344
401
  }
@@ -368,6 +425,86 @@ class MauticAdvanced {
368
425
  responseData = responseData.campaign;
369
426
  }
370
427
  }
428
+ if (resource === 'segment') {
429
+ //https://developer.mautic.org/#segments
430
+ if (operation === 'create') {
431
+ const name = this.getNodeParameter('name', i);
432
+ const additionalFields = this.getNodeParameter('additionalFields', i);
433
+ const body = {
434
+ name,
435
+ ...additionalFields,
436
+ };
437
+ responseData = await GenericFunctions_1.mauticApiRequest.call(this, 'POST', '/segments/new', body);
438
+ responseData = responseData.list; // Changed from .segment to .list
439
+ }
440
+ if (operation === 'update') {
441
+ const segmentId = this.getNodeParameter('segmentId', i);
442
+ const createIfNotFound = this.getNodeParameter('createIfNotFound', i);
443
+ const name = this.getNodeParameter('name', i);
444
+ const { ...additionalFields } = this.getNodeParameter('additionalFields', i);
445
+ const body = {
446
+ name,
447
+ ...additionalFields,
448
+ };
449
+ const method = createIfNotFound ? 'PUT' : 'PATCH';
450
+ responseData = await GenericFunctions_1.mauticApiRequest.call(this, method, `/segments/${segmentId}/edit`, body);
451
+ responseData = responseData.list; // Changed from .segment to .list
452
+ }
453
+ if (operation === 'get') {
454
+ const segmentId = this.getNodeParameter('segmentId', i);
455
+ responseData = await GenericFunctions_1.mauticApiRequest.call(this, 'GET', `/segments/${segmentId}`);
456
+ responseData = responseData.list; // Changed from .segment to .list
457
+ }
458
+ if (operation === 'getAll') {
459
+ const returnAll = this.getNodeParameter('returnAll', i);
460
+ const options = this.getNodeParameter('options', i);
461
+ qs = { ...options };
462
+ if (returnAll) {
463
+ responseData = await GenericFunctions_1.mauticApiRequestAllItems.call(this, 'lists', // Using 'lists' property name
464
+ 'GET', '/segments', {}, qs);
465
+ }
466
+ else {
467
+ const limit = this.getNodeParameter('limit', i);
468
+ qs.limit = limit;
469
+ responseData = await GenericFunctions_1.mauticApiRequest.call(this, 'GET', '/segments', {}, qs);
470
+ responseData = responseData.lists ? Object.values(responseData.lists) : []; // Convert object to array
471
+ }
472
+ }
473
+ if (operation === 'delete') {
474
+ const segmentId = this.getNodeParameter('segmentId', i);
475
+ responseData = await GenericFunctions_1.mauticApiRequest.call(this, 'DELETE', `/segments/${segmentId}/delete`);
476
+ responseData = responseData.list; // Changed from .segment to .list
477
+ }
478
+ if (operation === 'addContact') {
479
+ const segmentId = this.getNodeParameter('segmentId', i);
480
+ const contactId = this.getNodeParameter('contactId', i);
481
+ responseData = await GenericFunctions_1.mauticApiRequest.call(this, 'POST', `/segments/${segmentId}/contact/${contactId}/add`);
482
+ }
483
+ if (operation === 'removeContact') {
484
+ const segmentId = this.getNodeParameter('segmentId', i);
485
+ const contactId = this.getNodeParameter('contactId', i);
486
+ responseData = await GenericFunctions_1.mauticApiRequest.call(this, 'POST', `/segments/${segmentId}/contact/${contactId}/remove`);
487
+ }
488
+ if (operation === 'addContacts') {
489
+ const segmentId = this.getNodeParameter('segmentId', i);
490
+ let contactIds = this.getNodeParameter('contactIds', i, '');
491
+ if (!contactIds) {
492
+ // Fallback: collect from all input items
493
+ const ids = items
494
+ .map((item) => item.json.contactId || item.json.id)
495
+ .filter((id) => id !== undefined && id !== null && id !== '')
496
+ .map((id) => String(id));
497
+ contactIds = ids.join(',');
498
+ }
499
+ if (!contactIds) {
500
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No contact IDs provided or found in input items.');
501
+ }
502
+ const body = {
503
+ ids: contactIds.split(','),
504
+ };
505
+ responseData = await GenericFunctions_1.mauticApiRequest.call(this, 'POST', `/segments/${segmentId}/contacts/add`, body);
506
+ }
507
+ }
371
508
  if (resource === 'company') {
372
509
  //https://developer.mautic.org/#create-company
373
510
  if (operation === 'create') {
@@ -498,21 +635,19 @@ class MauticAdvanced {
498
635
  const simple = this.getNodeParameter('simple', i);
499
636
  const additionalFields = this.getNodeParameter('additionalFields', i);
500
637
  qs = Object.assign(qs, additionalFields);
501
- if (returnAll) {
502
- responseData = await GenericFunctions_1.mauticApiRequestAllItems.call(this, 'companies', 'GET', '/companies', {}, qs);
638
+ // Patch: enforce default sort order by id ascending if not set by user
639
+ if (!qs.orderBy) {
640
+ qs.orderBy = 'id';
503
641
  }
504
- else {
505
- qs.limit = this.getNodeParameter('limit', i);
506
- qs.start = 0;
507
- responseData = await GenericFunctions_1.mauticApiRequest.call(this, 'GET', '/companies', {}, qs);
508
- if (responseData.errors) {
509
- throw new n8n_workflow_1.NodeApiError(this.getNode(), responseData);
510
- }
511
- responseData = responseData.companies;
512
- responseData = Object.values(responseData);
642
+ if (!qs.orderByDir) {
643
+ qs.orderByDir = 'asc';
513
644
  }
645
+ let limit = undefined;
646
+ if (!returnAll) {
647
+ limit = this.getNodeParameter('limit', i);
648
+ }
649
+ responseData = await GenericFunctions_1.mauticApiRequestAllItems.call(this, 'companies', 'GET', '/companies', {}, qs, limit);
514
650
  if (simple) {
515
- //@ts-ignore
516
651
  responseData = responseData.map((item) => item.fields.all);
517
652
  }
518
653
  }
@@ -555,14 +690,18 @@ class MauticAdvanced {
555
690
  const returnAll = this.getNodeParameter('returnAll', i);
556
691
  const options = this.getNodeParameter('options', i);
557
692
  Object.assign(qs, options);
558
- if (returnAll) {
559
- responseData = await GenericFunctions_1.mauticApiRequestAllItems.call(this, 'tags', 'GET', '/tags', {}, qs);
693
+ // Patch: enforce default sort order by id ascending if not set by user
694
+ if (!qs.orderBy) {
695
+ qs.orderBy = 'id';
560
696
  }
561
- else {
562
- qs.limit = this.getNodeParameter('limit', i);
563
- responseData = await GenericFunctions_1.mauticApiRequest.call(this, 'GET', '/tags', {}, qs);
564
- responseData = responseData.tags;
697
+ if (!qs.orderByDir) {
698
+ qs.orderByDir = 'asc';
699
+ }
700
+ let limit = undefined;
701
+ if (!returnAll) {
702
+ limit = this.getNodeParameter('limit', i);
565
703
  }
704
+ responseData = await GenericFunctions_1.mauticApiRequestAllItems.call(this, 'tags', 'GET', '/tags', {}, qs, limit);
566
705
  }
567
706
  if (operation === 'delete') {
568
707
  const tagId = this.getNodeParameter('tagId', i);
@@ -802,30 +941,22 @@ class MauticAdvanced {
802
941
  const returnAll = this.getNodeParameter('returnAll', i);
803
942
  const options = this.getNodeParameter('options', i);
804
943
  qs = Object.assign(qs, options);
944
+ // Patch: enforce default sort order by id ascending if not set by user
945
+ if (!qs.orderBy) {
946
+ qs.orderBy = 'id';
947
+ }
948
+ if (!qs.orderByDir) {
949
+ qs.orderByDir = 'asc';
950
+ }
805
951
  if (qs.orderBy) {
806
952
  qs.orderBy = (0, change_case_1.snakeCase)(qs.orderBy);
807
953
  }
808
- if (returnAll) {
809
- responseData = await GenericFunctions_1.mauticApiRequestAllItems.call(this, 'contacts', 'GET', '/contacts', {}, qs);
810
- }
811
- else {
812
- const limit = this.getNodeParameter('limit', i);
813
- if (limit > 30) {
814
- responseData = await GenericFunctions_1.mauticApiRequestAllItems.call(this, 'contacts', 'GET', '/contacts', {}, qs, limit);
815
- }
816
- else {
817
- qs.limit = limit;
818
- qs.start = 0;
819
- responseData = await GenericFunctions_1.mauticApiRequest.call(this, 'GET', '/contacts', {}, qs);
820
- if (responseData.errors) {
821
- throw new n8n_workflow_1.NodeApiError(this.getNode(), responseData);
822
- }
823
- responseData = responseData.contacts;
824
- responseData = Object.values(responseData);
825
- }
954
+ let limit = undefined;
955
+ if (!returnAll) {
956
+ limit = this.getNodeParameter('limit', i);
826
957
  }
958
+ responseData = await GenericFunctions_1.mauticApiRequestAllItems.call(this, 'contacts', 'GET', '/contacts', {}, qs, limit);
827
959
  if (options.rawData === false) {
828
- //@ts-ignore
829
960
  responseData = responseData.map((item) => item.fields.all);
830
961
  }
831
962
  }
@@ -847,7 +978,9 @@ class MauticAdvanced {
847
978
  catch (error) {
848
979
  // If the error is a 404 (not found), treat as successful delete (idempotent)
849
980
  if (error instanceof n8n_workflow_1.NodeApiError && error.httpCode === '404') {
850
- responseData = [{ success: true, message: 'Contact already deleted or not found.' }];
981
+ responseData = [
982
+ { success: true, message: 'Contact already deleted or not found.' },
983
+ ];
851
984
  }
852
985
  else {
853
986
  throw error;
@@ -1039,19 +1172,15 @@ class MauticAdvanced {
1039
1172
  }
1040
1173
  if (operation === 'update') {
1041
1174
  const categoryId = this.getNodeParameter('categoryId', i);
1042
- const createIfNotFound = this.getNodeParameter('createIfNotFound', i);
1043
- const { title, bundle, description, color } = this.getNodeParameter('updateFields', i);
1175
+ const { title, description, color } = this.getNodeParameter('updateFields', i);
1044
1176
  const body = {};
1045
1177
  if (title)
1046
1178
  body.title = title;
1047
- if (bundle)
1048
- body.bundle = bundle;
1049
1179
  if (description)
1050
1180
  body.description = description;
1051
1181
  if (color)
1052
1182
  body.color = color;
1053
- const method = createIfNotFound ? 'PUT' : 'PATCH';
1054
- responseData = await GenericFunctions_1.mauticApiRequest.call(this, method, `/categories/${categoryId}/edit`, body);
1183
+ responseData = await GenericFunctions_1.mauticApiRequest.call(this, 'PATCH', `/categories/${categoryId}/edit`, body);
1055
1184
  responseData = responseData.category;
1056
1185
  }
1057
1186
  if (operation === 'get') {
@@ -1063,14 +1192,18 @@ class MauticAdvanced {
1063
1192
  const returnAll = this.getNodeParameter('returnAll', i);
1064
1193
  const options = this.getNodeParameter('options', i);
1065
1194
  Object.assign(qs, options);
1066
- if (returnAll) {
1067
- responseData = await GenericFunctions_1.mauticApiRequestAllItems.call(this, 'categories', 'GET', '/categories', {}, qs);
1195
+ // Patch: enforce default sort order by id ascending if not set by user
1196
+ if (!qs.orderBy) {
1197
+ qs.orderBy = 'id';
1068
1198
  }
1069
- else {
1070
- qs.limit = this.getNodeParameter('limit', i);
1071
- responseData = await GenericFunctions_1.mauticApiRequest.call(this, 'GET', '/categories', {}, qs);
1072
- responseData = responseData.categories;
1199
+ if (!qs.orderByDir) {
1200
+ qs.orderByDir = 'asc';
1201
+ }
1202
+ let limit = undefined;
1203
+ if (!returnAll) {
1204
+ limit = this.getNodeParameter('limit', i);
1073
1205
  }
1206
+ responseData = await GenericFunctions_1.mauticApiRequestAllItems.call(this, 'categories', 'GET', '/categories', {}, qs, limit);
1074
1207
  }
1075
1208
  if (operation === 'delete') {
1076
1209
  const categoryId = this.getNodeParameter('categoryId', i);
@@ -1078,12 +1211,16 @@ class MauticAdvanced {
1078
1211
  responseData = responseData.category;
1079
1212
  }
1080
1213
  }
1081
- const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
1082
- returnData.push(...executionData);
1214
+ if (Array.isArray(responseData)) {
1215
+ returnData.push(...this.helpers.returnJsonArray(responseData));
1216
+ }
1217
+ else {
1218
+ returnData.push(...this.helpers.returnJsonArray([responseData]));
1219
+ }
1083
1220
  }
1084
1221
  catch (error) {
1085
1222
  if (this.continueOnFail()) {
1086
- returnData.push({ json: { error: error.message } });
1223
+ returnData.push(...this.helpers.returnJsonArray([{ error: error.message }]));
1087
1224
  continue;
1088
1225
  }
1089
1226
  throw error;
@@ -1 +1,10 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="349.779" height="349.779"><path fill="#FFF" d="M174.89 349.779C78.612 349.779 0 271.462 0 174.89S78.612 0 174.89 0c23.26 0 45.931 4.417 67.129 13.543 5.889 2.65 8.833 9.422 6.478 15.605-2.649 5.888-9.421 8.833-15.604 6.477-18.549-7.655-37.98-11.482-58.002-11.482-83.323 0-151.041 67.718-151.041 151.041s67.717 151.041 151.04 151.041 151.041-67.718 151.041-151.041c0-17.96-2.944-35.332-9.127-51.819-2.355-6.183.883-12.955 7.066-15.31s12.954.883 15.31 7.066c7.066 19.138 10.6 39.453 10.6 60.063-.001 95.983-78.318 174.595-174.89 174.595"/><path fill="#FDB933" d="m251.44 156.93-27.086 28.264 15.015 63.302h34.153zm-11.187-83.618 9.421 9.422-74.784 79.201-63.891-65.658-36.803 152.219h34.154l20.315-84.5 46.225 50.347 98.927-107.76 9.422 9.716 9.421-53.292z"/></svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="349.779" height="349.779">
2
+ <path
3
+ fill="#FFF"
4
+ d="M174.89 349.779C78.612 349.779 0 271.462 0 174.89S78.612 0 174.89 0c23.26 0 45.931 4.417 67.129 13.543 5.889 2.65 8.833 9.422 6.478 15.605-2.649 5.888-9.421 8.833-15.604 6.477-18.549-7.655-37.98-11.482-58.002-11.482-83.323 0-151.041 67.718-151.041 151.041s67.717 151.041 151.04 151.041 151.041-67.718 151.041-151.041c0-17.96-2.944-35.332-9.127-51.819-2.355-6.183.883-12.955 7.066-15.31s12.954.883 15.31 7.066c7.066 19.138 10.6 39.453 10.6 60.063-.001 95.983-78.318 174.595-174.89 174.595"
5
+ />
6
+ <path
7
+ fill="#FDB933"
8
+ d="m251.44 156.93-27.086 28.264 15.015 63.302h34.153zm-11.187-83.618 9.421 9.422-74.784 79.201-63.891-65.658-36.803 152.219h34.154l20.315-84.5 46.225 50.347 98.927-107.76 9.422 9.716 9.421-53.292z"
9
+ />
10
+ </svg>
@@ -0,0 +1,360 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.segmentFields = exports.segmentOperations = void 0;
4
+ exports.segmentOperations = [
5
+ {
6
+ displayName: 'Operation',
7
+ name: 'operation',
8
+ type: 'options',
9
+ noDataExpression: true,
10
+ displayOptions: {
11
+ show: {
12
+ resource: ['segment'],
13
+ },
14
+ },
15
+ options: [
16
+ {
17
+ name: 'Add Contact',
18
+ value: 'addContact',
19
+ description: 'Add a contact to a segment',
20
+ action: 'Add a contact to a segment',
21
+ },
22
+ {
23
+ name: 'Add Contacts',
24
+ value: 'addContacts',
25
+ description: 'Add contacts to a segment',
26
+ action: 'Add contacts to a segment',
27
+ },
28
+ {
29
+ name: 'Create',
30
+ value: 'create',
31
+ description: 'Create a new segment',
32
+ action: 'Create a segment',
33
+ },
34
+ {
35
+ name: 'Delete',
36
+ value: 'delete',
37
+ description: 'Delete a segment',
38
+ action: 'Delete a segment',
39
+ },
40
+ {
41
+ name: 'Get',
42
+ value: 'get',
43
+ description: 'Get data of a segment',
44
+ action: 'Get a segment',
45
+ },
46
+ {
47
+ name: 'Get Many',
48
+ value: 'getAll',
49
+ description: 'Get data of many segments',
50
+ action: 'Get many segments',
51
+ },
52
+ {
53
+ name: 'Remove Contact',
54
+ value: 'removeContact',
55
+ description: 'Remove a contact from a segment',
56
+ action: 'Remove a contact from a segment',
57
+ },
58
+ {
59
+ name: 'Update',
60
+ value: 'update',
61
+ description: 'Update a segment',
62
+ action: 'Update a segment',
63
+ },
64
+ ],
65
+ default: 'create',
66
+ },
67
+ ];
68
+ exports.segmentFields = [
69
+ /* -------------------------------------------------------------------------- */
70
+ /* segment:create */
71
+ /* -------------------------------------------------------------------------- */
72
+ {
73
+ displayName: 'Name',
74
+ name: 'name',
75
+ type: 'string',
76
+ required: true,
77
+ displayOptions: {
78
+ show: {
79
+ resource: ['segment'],
80
+ operation: ['create', 'update'],
81
+ },
82
+ },
83
+ default: '',
84
+ },
85
+ {
86
+ displayName: 'Additional Fields',
87
+ name: 'additionalFields',
88
+ type: 'collection',
89
+ placeholder: 'Add Field',
90
+ default: {},
91
+ displayOptions: {
92
+ show: {
93
+ resource: ['segment'],
94
+ operation: ['create', 'update'],
95
+ },
96
+ },
97
+ options: [
98
+ {
99
+ displayName: 'Alias',
100
+ name: 'alias',
101
+ type: 'string',
102
+ default: '',
103
+ },
104
+ {
105
+ displayName: 'Description',
106
+ name: 'description',
107
+ type: 'string',
108
+ default: '',
109
+ },
110
+ {
111
+ displayName: 'Is Published',
112
+ name: 'isPublished',
113
+ type: 'boolean',
114
+ default: true,
115
+ },
116
+ {
117
+ displayName: 'Is Global',
118
+ name: 'isGlobal',
119
+ type: 'boolean',
120
+ default: false,
121
+ },
122
+ {
123
+ displayName: 'Filters',
124
+ name: 'filters',
125
+ type: 'fixedCollection',
126
+ placeholder: 'Add Filter',
127
+ typeOptions: {
128
+ multiple: true,
129
+ },
130
+ default: {},
131
+ options: [
132
+ {
133
+ displayName: 'Filter',
134
+ name: 'filter',
135
+ values: [
136
+ {
137
+ displayName: 'Glue',
138
+ name: 'glue',
139
+ type: 'options',
140
+ options: [
141
+ { name: 'And', value: 'and' },
142
+ { name: 'Or', value: 'or' },
143
+ ],
144
+ default: 'and',
145
+ },
146
+ {
147
+ displayName: 'Field',
148
+ name: 'field',
149
+ type: 'string',
150
+ default: 'email',
151
+ },
152
+ {
153
+ displayName: 'Object',
154
+ name: 'object',
155
+ type: 'options',
156
+ options: [
157
+ { name: 'Contact', value: 'lead' },
158
+ { name: 'Company', value: 'company' },
159
+ ],
160
+ default: 'lead',
161
+ },
162
+ {
163
+ displayName: 'Type',
164
+ name: 'type',
165
+ type: 'string',
166
+ default: 'email',
167
+ },
168
+ {
169
+ displayName: 'Filter',
170
+ name: 'filter',
171
+ type: 'string',
172
+ default: '',
173
+ },
174
+ {
175
+ displayName: 'Operator',
176
+ name: 'operator',
177
+ type: 'options',
178
+ options: [
179
+ { name: '=', value: '=' },
180
+ { name: '!=', value: '!=' },
181
+ { name: 'Empty', value: 'empty' },
182
+ { name: 'Not Empty', value: '!empty' },
183
+ { name: 'Like', value: 'like' },
184
+ { name: 'Not Like', value: '!like' },
185
+ { name: 'Regexp', value: 'regexp' },
186
+ { name: 'Not Regexp', value: '!regexp' },
187
+ { name: 'Starts With', value: 'startsWith' },
188
+ { name: 'Ends With', value: 'endsWith' },
189
+ { name: 'Contains', value: 'contains' },
190
+ ],
191
+ default: 'like',
192
+ },
193
+ ],
194
+ },
195
+ ],
196
+ },
197
+ ],
198
+ },
199
+ /* -------------------------------------------------------------------------- */
200
+ /* segment:update */
201
+ /* -------------------------------------------------------------------------- */
202
+ {
203
+ displayName: 'Segment ID',
204
+ name: 'segmentId',
205
+ type: 'string',
206
+ required: true,
207
+ displayOptions: {
208
+ show: {
209
+ resource: ['segment'],
210
+ operation: ['update', 'addContact', 'addContacts', 'removeContact'],
211
+ },
212
+ },
213
+ default: '',
214
+ },
215
+ {
216
+ displayName: 'Create If Not Found',
217
+ name: 'createIfNotFound',
218
+ type: 'boolean',
219
+ displayOptions: {
220
+ show: {
221
+ resource: ['segment'],
222
+ operation: ['update'],
223
+ },
224
+ },
225
+ default: false,
226
+ description: 'Whether to create a segment if the given ID is not found',
227
+ },
228
+ /* -------------------------------------------------------------------------- */
229
+ /* segment:get */
230
+ /* -------------------------------------------------------------------------- */
231
+ {
232
+ displayName: 'Segment ID',
233
+ name: 'segmentId',
234
+ type: 'string',
235
+ required: true,
236
+ displayOptions: {
237
+ show: {
238
+ resource: ['segment'],
239
+ operation: ['get', 'delete'],
240
+ },
241
+ },
242
+ default: '',
243
+ },
244
+ /* -------------------------------------------------------------------------- */
245
+ /* segment:getAll */
246
+ /* -------------------------------------------------------------------------- */
247
+ {
248
+ displayName: 'Return All',
249
+ name: 'returnAll',
250
+ type: 'boolean',
251
+ displayOptions: {
252
+ show: {
253
+ resource: ['segment'],
254
+ operation: ['getAll'],
255
+ },
256
+ },
257
+ default: false,
258
+ description: 'Whether to return all results or only up to a given limit',
259
+ },
260
+ {
261
+ displayName: 'Limit',
262
+ name: 'limit',
263
+ type: 'number',
264
+ displayOptions: {
265
+ show: {
266
+ resource: ['segment'],
267
+ operation: ['getAll'],
268
+ returnAll: [false],
269
+ },
270
+ },
271
+ typeOptions: {
272
+ minValue: 1,
273
+ },
274
+ default: 30,
275
+ description: 'Max number of results to return',
276
+ },
277
+ {
278
+ displayName: 'Options',
279
+ name: 'options',
280
+ type: 'collection',
281
+ placeholder: 'Add Option',
282
+ default: {},
283
+ displayOptions: {
284
+ show: {
285
+ resource: ['segment'],
286
+ operation: ['getAll'],
287
+ },
288
+ },
289
+ options: [
290
+ {
291
+ displayName: 'Search',
292
+ name: 'search',
293
+ type: 'string',
294
+ default: '',
295
+ description: 'String or search command to filter entities by',
296
+ },
297
+ {
298
+ displayName: 'Order By',
299
+ name: 'orderBy',
300
+ type: 'string',
301
+ default: '',
302
+ },
303
+ {
304
+ displayName: 'Order By Direction',
305
+ name: 'orderByDir',
306
+ type: 'options',
307
+ options: [
308
+ { name: 'ASC', value: 'asc' },
309
+ { name: 'DESC', value: 'desc' },
310
+ ],
311
+ default: 'asc',
312
+ },
313
+ {
314
+ displayName: 'Published Only',
315
+ name: 'publishedOnly',
316
+ type: 'boolean',
317
+ default: false,
318
+ },
319
+ {
320
+ displayName: 'Minimal',
321
+ name: 'minimal',
322
+ type: 'boolean',
323
+ default: false,
324
+ },
325
+ ],
326
+ },
327
+ /* -------------------------------------------------------------------------- */
328
+ /* segment:addContact */
329
+ /* -------------------------------------------------------------------------- */
330
+ {
331
+ displayName: 'Contact ID',
332
+ name: 'contactId',
333
+ type: 'string',
334
+ required: true,
335
+ displayOptions: {
336
+ show: {
337
+ resource: ['segment'],
338
+ operation: ['addContact', 'removeContact'],
339
+ },
340
+ },
341
+ default: '',
342
+ },
343
+ /* -------------------------------------------------------------------------- */
344
+ /* segment:addContacts */
345
+ /* -------------------------------------------------------------------------- */
346
+ {
347
+ displayName: 'Contact IDs',
348
+ name: 'contactIds',
349
+ type: 'string',
350
+ required: false,
351
+ displayOptions: {
352
+ show: {
353
+ resource: ['segment'],
354
+ operation: ['addContacts'],
355
+ },
356
+ },
357
+ default: '',
358
+ description: "Comma-separated list of contact IDs to add. If left empty, all input items' contactId or id fields will be used for batch adding.",
359
+ },
360
+ ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-mautic-advanced",
3
- "version": "0.2.0",
3
+ "version": "0.2.5",
4
4
  "description": "Enhanced n8n node for Mautic with comprehensive API coverage including tags, campaigns, categories, and advanced contact management",
5
5
  "keywords": [
6
6
  "n8n",
@@ -54,7 +54,9 @@
54
54
  "@typescript-eslint/eslint-plugin": "^7.7.0",
55
55
  "@typescript-eslint/parser": "^7.7.0",
56
56
  "eslint": "^8.57.0",
57
+ "eslint-config-prettier": "^10.1.5",
57
58
  "eslint-plugin-n8n-nodes-base": "^1.16.3",
59
+ "eslint-plugin-prettier": "^5.5.1",
58
60
  "gulp": "^4.0.2",
59
61
  "n8n-workflow": "^1.70.0",
60
62
  "prettier": "^3.2.5",