@belmontdigitalmarketing/n8n-nodes-flowlu 0.2.1 → 0.2.2

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.
@@ -9,9 +9,7 @@ async function getFlowluCredentials(context) {
9
9
  const credentials = await context.getCredentials('flowluApi');
10
10
  const subdomain = credentials.subdomain;
11
11
  const apiKey = credentials.apiKey;
12
- const baseUrl = subdomain.endsWith('.flowlu.com')
13
- ? `https://${subdomain}`
14
- : `https://${subdomain}.flowlu.com`;
12
+ const baseUrl = subdomain.endsWith('.flowlu.com') ? `https://${subdomain}` : `https://${subdomain}.flowlu.com`;
15
13
  return { baseUrl, apiKey };
16
14
  }
17
15
  async function flowluApiRequest(method, baseUrl, endpoint, apiKey, body, queryParams) {
@@ -31,6 +29,55 @@ async function flowluApiRequest(method, baseUrl, endpoint, apiKey, body, queryPa
31
29
  const response = await this.helpers.request(requestOptions);
32
30
  return typeof response === 'string' ? JSON.parse(response) : response;
33
31
  }
32
+ // Detect Flowlu's rate-limit signal in either a thrown error or a returned body.
33
+ function isFlowluRateLimit(value) {
34
+ const text = value instanceof Error ? value.message : typeof value === 'string' ? value : JSON.stringify(value ?? '');
35
+ return /limit exceeded|too many requests|\b429\b/i.test(text);
36
+ }
37
+ // GET wrapper that retries through Flowlu's rate limit with linear backoff. If it
38
+ // never succeeds it throws, so callers surface the real cause instead of silently
39
+ // returning no data (which previously masqueraded as "No fields found").
40
+ async function flowluApiGetWithRetry(baseUrl, endpoint, apiKey, queryParams, maxRetries = 3) {
41
+ let lastError = new Error('Flowlu request failed');
42
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
43
+ try {
44
+ const response = await flowluApiRequest.call(this, 'GET', baseUrl, endpoint, apiKey, undefined, queryParams);
45
+ if (!isFlowluRateLimit(response?.error ?? response)) {
46
+ return response;
47
+ }
48
+ lastError = new Error(String(response?.error ?? 'Flowlu request limit exceeded'));
49
+ }
50
+ catch (error) {
51
+ if (!isFlowluRateLimit(error))
52
+ throw error;
53
+ lastError = error;
54
+ }
55
+ // linear backoff before the next attempt (no wait after the final one)
56
+ if (attempt < maxRetries) {
57
+ await new Promise((resolve) => {
58
+ setTimeout(resolve, 1500 * (attempt + 1));
59
+ });
60
+ }
61
+ }
62
+ throw lastError instanceof Error ? lastError : new Error('Flowlu request failed');
63
+ }
64
+ // Fetch every page of a Flowlu list endpoint. The API caps responses at 50 items
65
+ // per page, so a single call silently truncates larger result sets.
66
+ async function flowluListAll(baseUrl, endpoint, apiKey) {
67
+ const items = [];
68
+ const maxPages = 100; // safety bound
69
+ for (let page = 1; page <= maxPages; page++) {
70
+ const response = await flowluApiGetWithRetry.call(this, baseUrl, endpoint, apiKey, { page: String(page) });
71
+ const pageItems = response?.response?.items;
72
+ if (!Array.isArray(pageItems) || pageItems.length === 0)
73
+ break;
74
+ items.push(...pageItems);
75
+ const total = Number(response.response.total ?? items.length);
76
+ if (items.length >= total)
77
+ break;
78
+ }
79
+ return items;
80
+ }
34
81
  function appendWorkflowFooter(target, contentKey = 'description') {
35
82
  const { id } = this.getWorkflow();
36
83
  const footer = `<hr><em>Generated via n8n:</em> <a href="${this.getInstanceBaseUrl()}workflow/${id}">View Workflow</a>`;
@@ -52,49 +99,27 @@ function applyResourceMapperFields(context, body, paramName, itemIndex) {
52
99
  // No custom fields set - ignore
53
100
  }
54
101
  }
55
- // Helper to load custom fields by module/model, with fallback approach
102
+ // Helper to load an entity's custom fields as name/value options.
56
103
  async function loadCustomFieldsForEntity(context, moduleFilter, modelFilter) {
104
+ const { baseUrl, apiKey } = await getFlowluCredentials(context);
105
+ let fieldsets;
106
+ let allFields;
57
107
  try {
58
- const { baseUrl, apiKey } = await getFlowluCredentials(context);
59
- // Strategy 1: Get all fieldsets and match by module/model
60
- const fieldsetsResponse = await flowluApiRequest.call(context, 'GET', baseUrl, '/api/v1/module/customfields/fieldsets/list', apiKey);
61
- const fieldsetIds = [];
62
- if (fieldsetsResponse?.response?.items) {
63
- for (const fs of fieldsetsResponse.response.items) {
64
- if (fs.module === moduleFilter && fs.model === modelFilter) {
65
- fieldsetIds.push(fs.id.toString());
66
- }
67
- }
68
- }
69
- // Get all custom fields
70
- const fieldsResponse = await flowluApiRequest.call(context, 'GET', baseUrl, '/api/v1/module/customfields/fields/list', apiKey);
71
- if (fieldsResponse?.response?.items) {
72
- let fields = fieldsResponse.response.items;
73
- // Filter by fieldset if we found matching fieldsets
74
- if (fieldsetIds.length > 0) {
75
- fields = fields.filter((f) => fieldsetIds.includes(f.fieldset_id?.toString()));
76
- }
77
- else {
78
- // Fallback: filter by module/model directly on the field
79
- fields = fields.filter((f) => f.module === moduleFilter && f.model === modelFilter);
80
- }
81
- return fields
82
- .filter((f) => f.active !== 0)
83
- .map((f) => {
84
- const cfKey = (f.api_use_alias && f.alias)
85
- ? `cf_${f.alias}`
86
- : `cf_${f.id}`;
87
- return {
88
- name: f.name || cfKey,
89
- value: cfKey,
90
- };
91
- });
92
- }
93
- return [];
108
+ fieldsets = await flowluListAll.call(context, baseUrl, '/api/v1/module/customfields/fieldsets/list', apiKey);
109
+ allFields = await flowluListAll.call(context, baseUrl, '/api/v1/module/customfields/fields/list', apiKey);
94
110
  }
95
111
  catch (error) {
96
- return [];
112
+ throw new n8n_workflow_1.NodeOperationError(context.getNode(), `Could not load Flowlu custom fields: ${error.message}. If this is a rate limit, wait a moment and try again.`);
97
113
  }
114
+ // Fields don't reliably carry module/model, so match via their fieldset.
115
+ const matchingFieldsetIds = new Set(fieldsets.filter((fs) => fs.module === moduleFilter && fs.model === modelFilter).map((fs) => String(fs.id)));
116
+ return allFields
117
+ .filter((f) => f.active !== 0)
118
+ .filter((f) => matchingFieldsetIds.has(String(f.fieldset_id)) || (f.module === moduleFilter && f.model === modelFilter))
119
+ .map((f) => {
120
+ const cfKey = f.api_use_alias && f.alias ? `cf_${f.alias}` : `cf_${f.id}`;
121
+ return { name: f.name || cfKey, value: cfKey };
122
+ });
98
123
  }
99
124
  // ============================================================
100
125
  // Reusable custom field option definitions
@@ -103,27 +128,16 @@ async function loadCustomFieldsForEntity(context, moduleFilter, modelFilter) {
103
128
  async function loadEntityCustomFieldColumns(moduleFilter, modelFilter) {
104
129
  try {
105
130
  const { baseUrl, apiKey } = await getFlowluCredentials(this);
106
- const fieldsetsResponse = await flowluApiRequest.call(this, 'GET', baseUrl, '/api/v1/module/customfields/fieldsets/list', apiKey);
107
- const fieldsetIds = [];
108
- if (fieldsetsResponse?.response?.items) {
109
- for (const fs of fieldsetsResponse.response.items) {
110
- if (fs.module === moduleFilter && fs.model === modelFilter) {
111
- fieldsetIds.push(fs.id.toString());
112
- }
113
- }
114
- }
115
- const fieldsResponse = await flowluApiRequest.call(this, 'GET', baseUrl, '/api/v1/module/customfields/fields/list', apiKey);
116
- if (!fieldsResponse?.response?.items)
117
- return { fields: [] };
118
- let filtered = fieldsResponse.response.items.filter((f) => f.active !== 0);
119
- if (fieldsetIds.length > 0) {
120
- filtered = filtered.filter((f) => fieldsetIds.includes(f.fieldset_id?.toString()));
121
- }
122
- else {
123
- filtered = filtered.filter((f) => f.module === moduleFilter && f.model === modelFilter);
124
- }
131
+ const fieldsets = await flowluListAll.call(this, baseUrl, '/api/v1/module/customfields/fieldsets/list', apiKey);
132
+ const allFields = await flowluListAll.call(this, baseUrl, '/api/v1/module/customfields/fields/list', apiKey);
133
+ // Fields don't reliably carry module/model, so match via their fieldset.
134
+ const matchingFieldsetIds = new Set(fieldsets
135
+ .filter((fs) => fs.module === moduleFilter && fs.model === modelFilter)
136
+ .map((fs) => String(fs.id)));
137
+ const filtered = allFields.filter((f) => f.active !== 0 &&
138
+ (matchingFieldsetIds.has(String(f.fieldset_id)) || (f.module === moduleFilter && f.model === modelFilter)));
125
139
  const fields = filtered.map((f) => {
126
- const cfKey = (f.api_use_alias && f.alias) ? `cf_${f.alias}` : `cf_${f.id}`;
140
+ const cfKey = f.api_use_alias && f.alias ? `cf_${f.alias}` : `cf_${f.id}`;
127
141
  let fieldType = 'string';
128
142
  if (f.type === 'int')
129
143
  fieldType = 'number';
@@ -145,7 +159,9 @@ async function loadEntityCustomFieldColumns(moduleFilter, modelFilter) {
145
159
  .filter((o) => o.value)
146
160
  .map((o) => ({ name: o.value, value: o.id?.toString() || o.value }));
147
161
  }
148
- catch { /* ignore */ }
162
+ catch {
163
+ /* ignore */
164
+ }
149
165
  }
150
166
  const field = {
151
167
  id: cfKey,
@@ -163,7 +179,9 @@ async function loadEntityCustomFieldColumns(moduleFilter, modelFilter) {
163
179
  return { fields };
164
180
  }
165
181
  catch (error) {
166
- return { fields: [] };
182
+ if (error instanceof n8n_workflow_1.NodeOperationError)
183
+ throw error;
184
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Could not load Flowlu custom fields: ${error.message}. If this is a rate limit, wait a moment and click Retry.`);
167
185
  }
168
186
  }
169
187
  function makeCustomFieldsOption(loadMethod) {
@@ -251,7 +269,12 @@ class Flowlu {
251
269
  displayOptions: { show: { resource: ['tag'] } },
252
270
  options: [
253
271
  { name: 'Add', value: 'add', description: 'Add a tag to an entity', action: 'Add a tag' },
254
- { name: 'Get Many', value: 'getAll', description: 'Get many tags on an entity', action: 'Get tags on entity' },
272
+ {
273
+ name: 'Get Many',
274
+ value: 'getAll',
275
+ description: 'Get many tags on an entity',
276
+ action: 'Get tags on entity',
277
+ },
255
278
  { name: 'List All', value: 'listAll', description: 'List all tags in your account', action: 'List all tags' },
256
279
  { name: 'Remove', value: 'remove', description: 'Remove a tag from an entity', action: 'Remove a tag' },
257
280
  ],
@@ -268,7 +291,12 @@ class Flowlu {
268
291
  displayOptions: { show: { resource: ['comment'] } },
269
292
  options: [
270
293
  { name: 'Create', value: 'create', description: 'Create a comment on an entity', action: 'Create a comment' },
271
- { name: 'Get Many', value: 'getAll', description: 'Get many comments on an entity', action: 'Get comments on entity' },
294
+ {
295
+ name: 'Get Many',
296
+ value: 'getAll',
297
+ description: 'Get many comments on an entity',
298
+ action: 'Get comments on entity',
299
+ },
272
300
  ],
273
301
  default: 'create',
274
302
  },
@@ -303,7 +331,12 @@ class Flowlu {
303
331
  { name: 'Create', value: 'create', description: 'Create a new opportunity', action: 'Create an opportunity' },
304
332
  { name: 'Delete', value: 'delete', description: 'Delete an opportunity', action: 'Delete an opportunity' },
305
333
  { name: 'Get', value: 'get', description: 'Get an opportunity by ID', action: 'Get an opportunity' },
306
- { name: 'Get Many', value: 'getAll', description: 'Get many opportunities', action: 'Get many opportunities' },
334
+ {
335
+ name: 'Get Many',
336
+ value: 'getAll',
337
+ description: 'Get many opportunities',
338
+ action: 'Get many opportunities',
339
+ },
307
340
  { name: 'Update', value: 'update', description: 'Update an opportunity', action: 'Update an opportunity' },
308
341
  ],
309
342
  default: 'create',
@@ -432,7 +465,14 @@ class Flowlu {
432
465
  { displayName: 'Instagram', name: 'social_network_link_6', type: 'string', default: '' },
433
466
  { displayName: 'LinkedIn', name: 'social_network_link_5', type: 'string', default: '' },
434
467
  { displayName: 'Middle Name', name: 'middle_name', type: 'string', default: '' },
435
- { displayName: 'Owner Name or ID', name: 'owner_id', type: 'options', typeOptions: { loadOptionsMethod: 'getUsers' }, default: '', description: 'Assigned user for this contact. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.' },
468
+ {
469
+ displayName: 'Owner Name or ID',
470
+ name: 'owner_id',
471
+ type: 'options',
472
+ typeOptions: { loadOptionsMethod: 'getUsers' },
473
+ default: '',
474
+ description: 'Assigned user for this contact. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
475
+ },
436
476
  { displayName: 'Personal Email', name: 'email_personal', type: 'string', default: '' },
437
477
  { displayName: 'Phone 2', name: 'phone2', type: 'string', default: '' },
438
478
  { displayName: 'Phone 3', name: 'phone3', type: 'string', default: '' },
@@ -491,7 +531,14 @@ class Flowlu {
491
531
  { displayName: 'Last Name', name: 'last_name', type: 'string', default: '' },
492
532
  { displayName: 'LinkedIn', name: 'social_network_link_5', type: 'string', default: '' },
493
533
  { displayName: 'Middle Name', name: 'middle_name', type: 'string', default: '' },
494
- { displayName: 'Owner Name or ID', name: 'owner_id', type: 'options', description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>', typeOptions: { loadOptionsMethod: 'getUsers' }, default: '' },
534
+ {
535
+ displayName: 'Owner Name or ID',
536
+ name: 'owner_id',
537
+ type: 'options',
538
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
539
+ typeOptions: { loadOptionsMethod: 'getUsers' },
540
+ default: '',
541
+ },
495
542
  { displayName: 'Personal Email', name: 'email_personal', type: 'string', default: '' },
496
543
  { displayName: 'Phone', name: 'phone', type: 'string', default: '' },
497
544
  { displayName: 'Phone 2', name: 'phone2', type: 'string', default: '' },
@@ -541,10 +588,23 @@ class Flowlu {
541
588
  displayOptions: { show: { resource: ['contact'], operation: ['getAll'] } },
542
589
  options: [
543
590
  { displayName: 'Name', name: 'name', type: 'string', default: '', description: 'Filter by contact name' },
544
- { displayName: 'Email', name: 'email', type: 'string',
545
- placeholder: 'name@email.com', default: '', description: 'Filter by email address' },
591
+ {
592
+ displayName: 'Email',
593
+ name: 'email',
594
+ type: 'string',
595
+ placeholder: 'name@email.com',
596
+ default: '',
597
+ description: 'Filter by email address',
598
+ },
546
599
  { displayName: 'Phone', name: 'phone', type: 'string', default: '', description: 'Filter by phone number' },
547
- { displayName: 'Owner Name or ID', name: 'owner_id', type: 'options', typeOptions: { loadOptionsMethod: 'getUsers' }, default: '', description: 'Filter by assigned owner. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.' },
600
+ {
601
+ displayName: 'Owner Name or ID',
602
+ name: 'owner_id',
603
+ type: 'options',
604
+ typeOptions: { loadOptionsMethod: 'getUsers' },
605
+ default: '',
606
+ description: 'Filter by assigned owner. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
607
+ },
548
608
  ],
549
609
  },
550
610
  // ========================================
@@ -606,11 +666,23 @@ class Flowlu {
606
666
  default: {},
607
667
  displayOptions: { show: { resource: ['opportunity'], operation: ['create'] } },
608
668
  options: [
609
- { displayName: 'Budget', name: 'budget', type: 'number', default: 0, description: 'Opportunity value/amount' },
669
+ {
670
+ displayName: 'Budget',
671
+ name: 'budget',
672
+ type: 'number',
673
+ default: 0,
674
+ description: 'Opportunity value/amount',
675
+ },
610
676
  { displayName: 'Contact Company', name: 'contact_company', type: 'string', default: '' },
611
677
  { displayName: 'Contact Email', name: 'contact_email', type: 'string', default: '' },
612
678
  { displayName: 'Contact Mobile', name: 'contact_mobile', type: 'string', default: '' },
613
- { displayName: 'Contact Name', name: 'contact_name', type: 'string', default: '', description: 'Quick-add contact name (if not linking to existing contact)' },
679
+ {
680
+ displayName: 'Contact Name',
681
+ name: 'contact_name',
682
+ type: 'string',
683
+ default: '',
684
+ description: 'Quick-add contact name (if not linking to existing contact)',
685
+ },
614
686
  { displayName: 'Contact Phone', name: 'contact_phone', type: 'string', default: '' },
615
687
  { displayName: 'Contact Position', name: 'contact_position', type: 'string', default: '' },
616
688
  { displayName: 'Contact Website', name: 'contact_web', type: 'string', default: '' },
@@ -622,10 +694,31 @@ class Flowlu {
622
694
  default: false,
623
695
  description: 'Whether to append a "Generated via n8n: View Workflow" footer to the opportunity description, linking back to this workflow',
624
696
  },
625
- { displayName: 'Link to Account Name or ID', name: 'link_account_id', type: 'options', typeOptions: { loadOptionsMethod: 'getAccounts' }, default: '', description: 'Link this opportunity to an existing CRM account (organization). Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.' },
626
- { displayName: 'Link to Contact Name or ID', name: 'link_contact_id', type: 'options', typeOptions: { loadOptionsMethod: 'getContacts' }, default: '', description: 'Link this opportunity to an existing CRM contact. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.' },
697
+ {
698
+ displayName: 'Link to Account Name or ID',
699
+ name: 'link_account_id',
700
+ type: 'options',
701
+ typeOptions: { loadOptionsMethod: 'getAccounts' },
702
+ default: '',
703
+ description: 'Link this opportunity to an existing CRM account (organization). Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
704
+ },
705
+ {
706
+ displayName: 'Link to Contact Name or ID',
707
+ name: 'link_contact_id',
708
+ type: 'options',
709
+ typeOptions: { loadOptionsMethod: 'getContacts' },
710
+ default: '',
711
+ description: 'Link this opportunity to an existing CRM contact. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
712
+ },
627
713
  { displayName: 'Planned Close Date', name: 'deadline', type: 'dateTime', default: '' },
628
- { displayName: 'Source Name or ID', name: 'source_id', type: 'options', typeOptions: { loadOptionsMethod: 'getOpportunitySources' }, default: '', description: 'Where this opportunity came from. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.' },
714
+ {
715
+ displayName: 'Source Name or ID',
716
+ name: 'source_id',
717
+ type: 'options',
718
+ typeOptions: { loadOptionsMethod: 'getOpportunitySources' },
719
+ default: '',
720
+ description: 'Where this opportunity came from. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
721
+ },
629
722
  { displayName: 'Start Date', name: 'start_date', type: 'dateTime', default: '' },
630
723
  ],
631
724
  },
@@ -655,9 +748,22 @@ class Flowlu {
655
748
  default: {},
656
749
  displayOptions: { show: { resource: ['opportunity'], operation: ['update'] } },
657
750
  options: [
658
- { displayName: 'Assignee Name or ID', name: 'assignee_id', type: 'options', description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>', typeOptions: { loadOptionsMethod: 'getUsers' }, default: '' },
751
+ {
752
+ displayName: 'Assignee Name or ID',
753
+ name: 'assignee_id',
754
+ type: 'options',
755
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
756
+ typeOptions: { loadOptionsMethod: 'getUsers' },
757
+ default: '',
758
+ },
659
759
  { displayName: 'Budget', name: 'budget', type: 'number', default: 0 },
660
- { displayName: 'Closing Comment', name: 'closing_comment', type: 'string', default: '', description: 'Reason for win/loss' },
760
+ {
761
+ displayName: 'Closing Comment',
762
+ name: 'closing_comment',
763
+ type: 'string',
764
+ default: '',
765
+ description: 'Reason for win/loss',
766
+ },
661
767
  { displayName: 'Contact Email', name: 'contact_email', type: 'string', default: '' },
662
768
  { displayName: 'Contact Name', name: 'contact_name', type: 'string', default: '' },
663
769
  { displayName: 'Contact Phone', name: 'contact_phone', type: 'string', default: '' },
@@ -669,11 +775,39 @@ class Flowlu {
669
775
  default: false,
670
776
  description: 'Whether to append a "Generated via n8n: View Workflow" footer to the opportunity description, linking back to this workflow. Requires Description to be set.',
671
777
  },
672
- { displayName: 'Link to Account Name or ID', name: 'link_account_id', type: 'options', typeOptions: { loadOptionsMethod: 'getAccounts' }, default: '', description: 'Link this opportunity to a CRM account. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.' },
673
- { displayName: 'Link to Contact Name or ID', name: 'link_contact_id', type: 'options', typeOptions: { loadOptionsMethod: 'getContacts' }, default: '', description: 'Link this opportunity to a CRM contact. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.' },
778
+ {
779
+ displayName: 'Link to Account Name or ID',
780
+ name: 'link_account_id',
781
+ type: 'options',
782
+ typeOptions: { loadOptionsMethod: 'getAccounts' },
783
+ default: '',
784
+ description: 'Link this opportunity to a CRM account. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
785
+ },
786
+ {
787
+ displayName: 'Link to Contact Name or ID',
788
+ name: 'link_contact_id',
789
+ type: 'options',
790
+ typeOptions: { loadOptionsMethod: 'getContacts' },
791
+ default: '',
792
+ description: 'Link this opportunity to a CRM contact. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
793
+ },
674
794
  { displayName: 'Name', name: 'name', type: 'string', default: '' },
675
- { displayName: 'Pipeline Name or ID', name: 'pipeline_id', type: 'options', description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>', typeOptions: { loadOptionsMethod: 'getPipelines' }, default: '' },
676
- { displayName: 'Pipeline Stage Name or ID', name: 'pipeline_stage_id', type: 'options', description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>', typeOptions: { loadOptionsMethod: 'getPipelineStages' }, default: '' },
795
+ {
796
+ displayName: 'Pipeline Name or ID',
797
+ name: 'pipeline_id',
798
+ type: 'options',
799
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
800
+ typeOptions: { loadOptionsMethod: 'getPipelines' },
801
+ default: '',
802
+ },
803
+ {
804
+ displayName: 'Pipeline Stage Name or ID',
805
+ name: 'pipeline_stage_id',
806
+ type: 'options',
807
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
808
+ typeOptions: { loadOptionsMethod: 'getPipelineStages' },
809
+ default: '',
810
+ },
677
811
  { displayName: 'Planned Close Date', name: 'deadline', type: 'dateTime', default: '' },
678
812
  { displayName: 'Start Date', name: 'start_date', type: 'dateTime', default: '' },
679
813
  {
@@ -748,8 +882,22 @@ class Flowlu {
748
882
  displayOptions: { show: { resource: ['opportunity'], operation: ['getAll'] } },
749
883
  options: [
750
884
  { displayName: 'Name', name: 'name', type: 'string', default: '', description: 'Filter by opportunity name' },
751
- { displayName: 'Assignee Name or ID', name: 'assignee_id', type: 'options', description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>', typeOptions: { loadOptionsMethod: 'getUsers' }, default: '' },
752
- { displayName: 'Account / Contact Name or ID', name: 'company_id', type: 'options', typeOptions: { loadOptionsMethod: 'getAllCrmAccounts' }, default: '', description: 'Filter by linked company or contact (note: Flowlu may not support this filter). Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.' },
885
+ {
886
+ displayName: 'Assignee Name or ID',
887
+ name: 'assignee_id',
888
+ type: 'options',
889
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
890
+ typeOptions: { loadOptionsMethod: 'getUsers' },
891
+ default: '',
892
+ },
893
+ {
894
+ displayName: 'Account / Contact Name or ID',
895
+ name: 'company_id',
896
+ type: 'options',
897
+ typeOptions: { loadOptionsMethod: 'getAllCrmAccounts' },
898
+ default: '',
899
+ description: 'Filter by linked company or contact (note: Flowlu may not support this filter). Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
900
+ },
753
901
  {
754
902
  displayName: 'Status',
755
903
  name: 'active',
@@ -823,8 +971,22 @@ class Flowlu {
823
971
  default: 0,
824
972
  },
825
973
  { displayName: 'Contract Sum (Revenue)', name: 'estimated_revenue', type: 'number', default: 0 },
826
- { displayName: 'Customer (Company ID) Name or ID', name: 'customer_id', type: 'options', typeOptions: { loadOptionsMethod: 'getContacts' }, default: '', description: 'CRM company linked to this project. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.' },
827
- { displayName: 'Customer Contact Name or ID', name: 'customer_crm_contact_id', type: 'options', typeOptions: { loadOptionsMethod: 'getContacts' }, default: '', description: 'CRM contact linked to this project. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.' },
974
+ {
975
+ displayName: 'Customer (Company ID) Name or ID',
976
+ name: 'customer_id',
977
+ type: 'options',
978
+ typeOptions: { loadOptionsMethod: 'getContacts' },
979
+ default: '',
980
+ description: 'CRM company linked to this project. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
981
+ },
982
+ {
983
+ displayName: 'Customer Contact Name or ID',
984
+ name: 'customer_crm_contact_id',
985
+ type: 'options',
986
+ typeOptions: { loadOptionsMethod: 'getContacts' },
987
+ default: '',
988
+ description: 'CRM contact linked to this project. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
989
+ },
828
990
  { displayName: 'End Date', name: 'enddate', type: 'dateTime', default: '' },
829
991
  { displayName: 'Expense Sum', name: 'estimated_expenses', type: 'number', default: 0 },
830
992
  {
@@ -834,8 +996,21 @@ class Flowlu {
834
996
  default: false,
835
997
  description: 'Whether to append a "Generated via n8n: View Workflow" footer to the project description, linking back to this workflow',
836
998
  },
837
- { displayName: 'Opportunity', name: 'crm_lead_id', type: 'number', default: 0, description: 'ID of a linked CRM opportunity' },
838
- { displayName: 'Portfolio Name or ID', name: 'briefcase_id', type: 'options', description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>', typeOptions: { loadOptionsMethod: 'getPortfolios' }, default: '' },
999
+ {
1000
+ displayName: 'Opportunity',
1001
+ name: 'crm_lead_id',
1002
+ type: 'number',
1003
+ default: 0,
1004
+ description: 'ID of a linked CRM opportunity',
1005
+ },
1006
+ {
1007
+ displayName: 'Portfolio Name or ID',
1008
+ name: 'briefcase_id',
1009
+ type: 'options',
1010
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
1011
+ typeOptions: { loadOptionsMethod: 'getPortfolios' },
1012
+ default: '',
1013
+ },
839
1014
  {
840
1015
  displayName: 'Priority',
841
1016
  name: 'priority',
@@ -847,9 +1022,23 @@ class Flowlu {
847
1022
  ],
848
1023
  default: 2,
849
1024
  },
850
- { displayName: 'Project Stage Name or ID', name: 'stage_id', type: 'options', description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>', typeOptions: { loadOptionsMethod: 'getProjectStages' }, default: '' },
1025
+ {
1026
+ displayName: 'Project Stage Name or ID',
1027
+ name: 'stage_id',
1028
+ type: 'options',
1029
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
1030
+ typeOptions: { loadOptionsMethod: 'getProjectStages' },
1031
+ default: '',
1032
+ },
851
1033
  { displayName: 'Start Date', name: 'startdate', type: 'dateTime', default: '' },
852
- { displayName: 'Task Workflow Name or ID', name: 'tasks_workflow_id', type: 'options', typeOptions: { loadOptionsMethod: 'getTaskWorkflows' }, default: '', description: 'Default task workflow for tasks in this project. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.' },
1034
+ {
1035
+ displayName: 'Task Workflow Name or ID',
1036
+ name: 'tasks_workflow_id',
1037
+ type: 'options',
1038
+ typeOptions: { loadOptionsMethod: 'getTaskWorkflows' },
1039
+ default: '',
1040
+ description: 'Default task workflow for tasks in this project. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
1041
+ },
853
1042
  ],
854
1043
  },
855
1044
  {
@@ -895,7 +1084,14 @@ class Flowlu {
895
1084
  default: false,
896
1085
  description: 'Whether to append a "Generated via n8n: View Workflow" footer to the project description, linking back to this workflow. Requires Description to be set.',
897
1086
  },
898
- { displayName: 'Manager Name or ID', name: 'manager_id', type: 'options', description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>', typeOptions: { loadOptionsMethod: 'getUsers' }, default: '' },
1087
+ {
1088
+ displayName: 'Manager Name or ID',
1089
+ name: 'manager_id',
1090
+ type: 'options',
1091
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
1092
+ typeOptions: { loadOptionsMethod: 'getUsers' },
1093
+ default: '',
1094
+ },
899
1095
  {
900
1096
  displayName: 'Priority',
901
1097
  name: 'priority',
@@ -908,7 +1104,14 @@ class Flowlu {
908
1104
  default: 2,
909
1105
  },
910
1106
  { displayName: 'Project Name', name: 'name', type: 'string', default: '' },
911
- { displayName: 'Project Stage Name or ID', name: 'stage_id', type: 'options', description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>', typeOptions: { loadOptionsMethod: 'getProjectStages' }, default: '' },
1107
+ {
1108
+ displayName: 'Project Stage Name or ID',
1109
+ name: 'stage_id',
1110
+ type: 'options',
1111
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
1112
+ typeOptions: { loadOptionsMethod: 'getProjectStages' },
1113
+ default: '',
1114
+ },
912
1115
  { displayName: 'Start Date', name: 'startdate', type: 'dateTime', default: '' },
913
1116
  ],
914
1117
  },
@@ -950,8 +1153,22 @@ class Flowlu {
950
1153
  displayOptions: { show: { resource: ['project'], operation: ['getAll'] } },
951
1154
  options: [
952
1155
  { displayName: 'Name', name: 'name', type: 'string', default: '', description: 'Filter by project name' },
953
- { displayName: 'Manager Name or ID', name: 'manager_id', type: 'options', description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>', typeOptions: { loadOptionsMethod: 'getUsers' }, default: '' },
954
- { displayName: 'Customer Name or ID', name: 'customer_id', type: 'options', typeOptions: { loadOptionsMethod: 'getAccounts' }, default: '', description: 'Filter by linked company. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.' },
1156
+ {
1157
+ displayName: 'Manager Name or ID',
1158
+ name: 'manager_id',
1159
+ type: 'options',
1160
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
1161
+ typeOptions: { loadOptionsMethod: 'getUsers' },
1162
+ default: '',
1163
+ },
1164
+ {
1165
+ displayName: 'Customer Name or ID',
1166
+ name: 'customer_id',
1167
+ type: 'options',
1168
+ typeOptions: { loadOptionsMethod: 'getAccounts' },
1169
+ default: '',
1170
+ description: 'Filter by linked company. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
1171
+ },
955
1172
  {
956
1173
  displayName: 'Include Archived',
957
1174
  name: 'is_archive',
@@ -1046,7 +1263,13 @@ class Flowlu {
1046
1263
  default: {},
1047
1264
  displayOptions: { show: { resource: ['recordList'], operation: ['getAll'] } },
1048
1265
  options: [
1049
- { displayName: 'Search', name: 'search', type: 'string', default: '', description: 'Search records by name/content' },
1266
+ {
1267
+ displayName: 'Search',
1268
+ name: 'search',
1269
+ type: 'string',
1270
+ default: '',
1271
+ description: 'Search records by name/content',
1272
+ },
1050
1273
  ],
1051
1274
  },
1052
1275
  // ========================================
@@ -1098,7 +1321,14 @@ class Flowlu {
1098
1321
  displayOptions: { show: { resource: ['task'], operation: ['create'] } },
1099
1322
  options: [
1100
1323
  { displayName: 'Allow End Date Change', name: 'deadline_allowchange', type: 'boolean', default: true },
1101
- { displayName: 'Contact Name or ID', name: 'contact_id', type: 'options', typeOptions: { loadOptionsMethod: 'getContacts' }, default: '', description: 'The contact this task is related to. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.' },
1324
+ {
1325
+ displayName: 'Contact Name or ID',
1326
+ name: 'contact_id',
1327
+ type: 'options',
1328
+ typeOptions: { loadOptionsMethod: 'getContacts' },
1329
+ default: '',
1330
+ description: 'The contact this task is related to. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
1331
+ },
1102
1332
  { displayName: 'End Date', name: 'deadline', type: 'dateTime', default: '' },
1103
1333
  {
1104
1334
  displayName: 'Include Link to Workflow',
@@ -1107,8 +1337,21 @@ class Flowlu {
1107
1337
  default: false,
1108
1338
  description: 'Whether to append a "Generated via n8n: View Workflow" footer to the task description, linking back to this workflow',
1109
1339
  },
1110
- { displayName: 'Owner Name or ID', name: 'owner_id', type: 'options', typeOptions: { loadOptionsMethod: 'getUsers' }, description: 'The user who owns/created this task. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.', default: '' },
1111
- { displayName: 'Parent Task ID', name: 'parent_id', type: 'number', default: 0, description: 'ID of the parent task (for subtasks)' },
1340
+ {
1341
+ displayName: 'Owner Name or ID',
1342
+ name: 'owner_id',
1343
+ type: 'options',
1344
+ typeOptions: { loadOptionsMethod: 'getUsers' },
1345
+ description: 'The user who owns/created this task. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
1346
+ default: '',
1347
+ },
1348
+ {
1349
+ displayName: 'Parent Task ID',
1350
+ name: 'parent_id',
1351
+ type: 'number',
1352
+ default: 0,
1353
+ description: 'ID of the parent task (for subtasks)',
1354
+ },
1112
1355
  { displayName: 'Planned Cost', name: 'cost', type: 'number', default: 0, typeOptions: { minValue: 0 } },
1113
1356
  { displayName: 'Planned Income', name: 'price', type: 'number', default: 0, typeOptions: { minValue: 0 } },
1114
1357
  {
@@ -1122,7 +1365,14 @@ class Flowlu {
1122
1365
  ],
1123
1366
  default: 2,
1124
1367
  },
1125
- { displayName: 'Project Name or ID', name: 'model_id', type: 'options', typeOptions: { loadOptionsMethod: 'getProjects' }, description: 'The project this task belongs to. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.', default: '' },
1368
+ {
1369
+ displayName: 'Project Name or ID',
1370
+ name: 'model_id',
1371
+ type: 'options',
1372
+ typeOptions: { loadOptionsMethod: 'getProjects' },
1373
+ description: 'The project this task belongs to. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
1374
+ default: '',
1375
+ },
1126
1376
  { displayName: 'Reviewed by Owner', name: 'task_checkbyowner', type: 'boolean', default: false },
1127
1377
  { displayName: 'Start Date', name: 'plan_start_date', type: 'dateTime', default: '' },
1128
1378
  {
@@ -1137,9 +1387,29 @@ class Flowlu {
1137
1387
  ],
1138
1388
  default: 1,
1139
1389
  },
1140
- { displayName: 'Time Estimate (Minutes)', name: 'time_estimate', type: 'number', default: 0, typeOptions: { minValue: 0 } },
1141
- { displayName: 'Workflow Name or ID', name: 'workflow_id', type: 'options', typeOptions: { loadOptionsMethod: 'getTaskWorkflows' }, default: '', description: 'The task workflow to use (defaults to the first workflow if not set). Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.' },
1142
- { displayName: 'Workflow Stage Name or ID', name: 'workflow_stage_id', type: 'options', typeOptions: { loadOptionsMethod: 'getTaskWorkflowStages' }, default: '', description: 'The starting stage within the workflow. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.' },
1390
+ {
1391
+ displayName: 'Time Estimate (Minutes)',
1392
+ name: 'time_estimate',
1393
+ type: 'number',
1394
+ default: 0,
1395
+ typeOptions: { minValue: 0 },
1396
+ },
1397
+ {
1398
+ displayName: 'Workflow Name or ID',
1399
+ name: 'workflow_id',
1400
+ type: 'options',
1401
+ typeOptions: { loadOptionsMethod: 'getTaskWorkflows' },
1402
+ default: '',
1403
+ description: 'The task workflow to use (defaults to the first workflow if not set). Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
1404
+ },
1405
+ {
1406
+ displayName: 'Workflow Stage Name or ID',
1407
+ name: 'workflow_stage_id',
1408
+ type: 'options',
1409
+ typeOptions: { loadOptionsMethod: 'getTaskWorkflowStages' },
1410
+ default: '',
1411
+ description: 'The starting stage within the workflow. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
1412
+ },
1143
1413
  ],
1144
1414
  },
1145
1415
  {
@@ -1168,7 +1438,14 @@ class Flowlu {
1168
1438
  default: {},
1169
1439
  displayOptions: { show: { resource: ['task'], operation: ['update'] } },
1170
1440
  options: [
1171
- { displayName: 'Assignee Name or ID', name: 'responsible_id', type: 'options', description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>', typeOptions: { loadOptionsMethod: 'getUsers' }, default: '' },
1441
+ {
1442
+ displayName: 'Assignee Name or ID',
1443
+ name: 'responsible_id',
1444
+ type: 'options',
1445
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
1446
+ typeOptions: { loadOptionsMethod: 'getUsers' },
1447
+ default: '',
1448
+ },
1172
1449
  { displayName: 'Description', name: 'description', type: 'string', typeOptions: { rows: 4 }, default: '' },
1173
1450
  { displayName: 'End Date', name: 'deadline', type: 'dateTime', default: '' },
1174
1451
  {
@@ -1178,7 +1455,14 @@ class Flowlu {
1178
1455
  default: false,
1179
1456
  description: 'Whether to append a "Generated via n8n: View Workflow" footer to the task description, linking back to this workflow. Requires Description to be set.',
1180
1457
  },
1181
- { displayName: 'Owner Name or ID', name: 'owner_id', type: 'options', description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>', typeOptions: { loadOptionsMethod: 'getUsers' }, default: '' },
1458
+ {
1459
+ displayName: 'Owner Name or ID',
1460
+ name: 'owner_id',
1461
+ type: 'options',
1462
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
1463
+ typeOptions: { loadOptionsMethod: 'getUsers' },
1464
+ default: '',
1465
+ },
1182
1466
  { displayName: 'Parent Task ID', name: 'parent_id', type: 'number', default: 0 },
1183
1467
  { displayName: 'Planned Cost', name: 'cost', type: 'number', default: 0, typeOptions: { minValue: 0 } },
1184
1468
  { displayName: 'Planned Income', name: 'price', type: 'number', default: 0, typeOptions: { minValue: 0 } },
@@ -1193,7 +1477,14 @@ class Flowlu {
1193
1477
  ],
1194
1478
  default: 2,
1195
1479
  },
1196
- { displayName: 'Project Name or ID', name: 'model_id', type: 'options', description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>', typeOptions: { loadOptionsMethod: 'getProjects' }, default: '' },
1480
+ {
1481
+ displayName: 'Project Name or ID',
1482
+ name: 'model_id',
1483
+ type: 'options',
1484
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
1485
+ typeOptions: { loadOptionsMethod: 'getProjects' },
1486
+ default: '',
1487
+ },
1197
1488
  { displayName: 'Start Date', name: 'plan_start_date', type: 'dateTime', default: '' },
1198
1489
  {
1199
1490
  displayName: 'Status',
@@ -1208,9 +1499,29 @@ class Flowlu {
1208
1499
  default: 1,
1209
1500
  },
1210
1501
  { displayName: 'Task Name', name: 'name', type: 'string', default: '' },
1211
- { displayName: 'Time Estimate (Minutes)', name: 'time_estimate', type: 'number', default: 0, typeOptions: { minValue: 0 } },
1212
- { displayName: 'Workflow Name or ID', name: 'workflow_id', type: 'options', description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>', typeOptions: { loadOptionsMethod: 'getTaskWorkflows' }, default: '' },
1213
- { displayName: 'Workflow Stage Name or ID', name: 'workflow_stage_id', type: 'options', description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>', typeOptions: { loadOptionsMethod: 'getTaskWorkflowStages' }, default: '' },
1502
+ {
1503
+ displayName: 'Time Estimate (Minutes)',
1504
+ name: 'time_estimate',
1505
+ type: 'number',
1506
+ default: 0,
1507
+ typeOptions: { minValue: 0 },
1508
+ },
1509
+ {
1510
+ displayName: 'Workflow Name or ID',
1511
+ name: 'workflow_id',
1512
+ type: 'options',
1513
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
1514
+ typeOptions: { loadOptionsMethod: 'getTaskWorkflows' },
1515
+ default: '',
1516
+ },
1517
+ {
1518
+ displayName: 'Workflow Stage Name or ID',
1519
+ name: 'workflow_stage_id',
1520
+ type: 'options',
1521
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
1522
+ typeOptions: { loadOptionsMethod: 'getTaskWorkflowStages' },
1523
+ default: '',
1524
+ },
1214
1525
  ],
1215
1526
  },
1216
1527
  {
@@ -1250,7 +1561,14 @@ class Flowlu {
1250
1561
  default: {},
1251
1562
  displayOptions: { show: { resource: ['task'], operation: ['getAll'] } },
1252
1563
  options: [
1253
- { displayName: 'Assignee Name or ID', name: 'responsible_id', type: 'options', description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>', typeOptions: { loadOptionsMethod: 'getUsers' }, default: '' },
1564
+ {
1565
+ displayName: 'Assignee Name or ID',
1566
+ name: 'responsible_id',
1567
+ type: 'options',
1568
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
1569
+ typeOptions: { loadOptionsMethod: 'getUsers' },
1570
+ default: '',
1571
+ },
1254
1572
  { displayName: 'Name', name: 'name', type: 'string', default: '', description: 'Filter by task name' },
1255
1573
  {
1256
1574
  displayName: 'Priority',
@@ -1263,7 +1581,14 @@ class Flowlu {
1263
1581
  ],
1264
1582
  default: 2,
1265
1583
  },
1266
- { displayName: 'Project Name or ID', name: 'model_id', type: 'options', description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>', typeOptions: { loadOptionsMethod: 'getProjects' }, default: '' },
1584
+ {
1585
+ displayName: 'Project Name or ID',
1586
+ name: 'model_id',
1587
+ type: 'options',
1588
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
1589
+ typeOptions: { loadOptionsMethod: 'getProjects' },
1590
+ default: '',
1591
+ },
1267
1592
  {
1268
1593
  displayName: 'Status',
1269
1594
  name: 'status',
@@ -1388,7 +1713,10 @@ class Flowlu {
1388
1713
  const { baseUrl, apiKey } = await getFlowluCredentials(this);
1389
1714
  const response = await flowluApiRequest.call(this, 'GET', baseUrl, '/api/v1/module/core/user/list', apiKey, undefined, { 'filter[role_login]': '1' });
1390
1715
  if (response?.response?.items) {
1391
- return response.response.items.map((user) => ({ name: user.name || user.email || `User ${user.id}`, value: user.id.toString() }));
1716
+ return response.response.items.map((user) => ({
1717
+ name: user.name || user.email || `User ${user.id}`,
1718
+ value: user.id.toString(),
1719
+ }));
1392
1720
  }
1393
1721
  return [];
1394
1722
  }
@@ -1401,7 +1729,10 @@ class Flowlu {
1401
1729
  const { baseUrl, apiKey } = await getFlowluCredentials(this);
1402
1730
  const response = await flowluApiRequest.call(this, 'GET', baseUrl, '/api/v1/module/crm/account/list', apiKey, undefined, { 'filter[type]': '1' });
1403
1731
  if (response?.response?.items) {
1404
- return response.response.items.map((a) => ({ name: a.name || `Account ${a.id}`, value: a.id.toString() }));
1732
+ return response.response.items.map((a) => ({
1733
+ name: a.name || `Account ${a.id}`,
1734
+ value: a.id.toString(),
1735
+ }));
1405
1736
  }
1406
1737
  return [];
1407
1738
  }
@@ -1414,7 +1745,10 @@ class Flowlu {
1414
1745
  const { baseUrl, apiKey } = await getFlowluCredentials(this);
1415
1746
  const response = await flowluApiRequest.call(this, 'GET', baseUrl, '/api/v1/module/crm/account/list', apiKey, undefined, { 'filter[type]': '2' });
1416
1747
  if (response?.response?.items) {
1417
- return response.response.items.map((c) => ({ name: c.name || `Contact ${c.id}`, value: c.id.toString() }));
1748
+ return response.response.items.map((c) => ({
1749
+ name: c.name || `Contact ${c.id}`,
1750
+ value: c.id.toString(),
1751
+ }));
1418
1752
  }
1419
1753
  return [];
1420
1754
  }
@@ -1427,7 +1761,10 @@ class Flowlu {
1427
1761
  const { baseUrl, apiKey } = await getFlowluCredentials(this);
1428
1762
  const response = await flowluApiRequest.call(this, 'GET', baseUrl, '/api/v1/module/st/projects/list', apiKey, undefined, { 'filter[is_archive]': '0' });
1429
1763
  if (response?.response?.items) {
1430
- return response.response.items.map((p) => ({ name: p.name || `Project ${p.id}`, value: p.id.toString() }));
1764
+ return response.response.items.map((p) => ({
1765
+ name: p.name || `Project ${p.id}`,
1766
+ value: p.id.toString(),
1767
+ }));
1431
1768
  }
1432
1769
  return [];
1433
1770
  }
@@ -1440,7 +1777,10 @@ class Flowlu {
1440
1777
  const { baseUrl, apiKey } = await getFlowluCredentials(this);
1441
1778
  const response = await flowluApiRequest.call(this, 'GET', baseUrl, '/api/v1/module/task/workflows/list', apiKey);
1442
1779
  if (response?.response?.items) {
1443
- return response.response.items.map((wf) => ({ name: wf.name || `Workflow ${wf.id}`, value: wf.id.toString() }));
1780
+ return response.response.items.map((wf) => ({
1781
+ name: wf.name || `Workflow ${wf.id}`,
1782
+ value: wf.id.toString(),
1783
+ }));
1444
1784
  }
1445
1785
  return [];
1446
1786
  }
@@ -1453,7 +1793,11 @@ class Flowlu {
1453
1793
  const { baseUrl, apiKey } = await getFlowluCredentials(this);
1454
1794
  const response = await flowluApiRequest.call(this, 'GET', baseUrl, '/api/v1/module/task/stages/list', apiKey);
1455
1795
  if (response?.response?.items) {
1456
- return response.response.items.map((s) => ({ name: s.name || `Stage ${s.id}`, value: s.id.toString(), description: `Workflow ID: ${s.workflow_id}` }));
1796
+ return response.response.items.map((s) => ({
1797
+ name: s.name || `Stage ${s.id}`,
1798
+ value: s.id.toString(),
1799
+ description: `Workflow ID: ${s.workflow_id}`,
1800
+ }));
1457
1801
  }
1458
1802
  return [];
1459
1803
  }
@@ -1466,7 +1810,10 @@ class Flowlu {
1466
1810
  const { baseUrl, apiKey } = await getFlowluCredentials(this);
1467
1811
  const response = await flowluApiRequest.call(this, 'GET', baseUrl, '/api/v1/module/crm/pipeline/list', apiKey);
1468
1812
  if (response?.response?.items) {
1469
- return response.response.items.map((p) => ({ name: p.name || `Pipeline ${p.id}`, value: p.id.toString() }));
1813
+ return response.response.items.map((p) => ({
1814
+ name: p.name || `Pipeline ${p.id}`,
1815
+ value: p.id.toString(),
1816
+ }));
1470
1817
  }
1471
1818
  return [];
1472
1819
  }
@@ -1479,7 +1826,11 @@ class Flowlu {
1479
1826
  const { baseUrl, apiKey } = await getFlowluCredentials(this);
1480
1827
  const response = await flowluApiRequest.call(this, 'GET', baseUrl, '/api/v1/module/crm/pipeline_stage/list', apiKey);
1481
1828
  if (response?.response?.items) {
1482
- return response.response.items.map((s) => ({ name: s.name || `Stage ${s.id}`, value: s.id.toString(), description: `Pipeline ID: ${s.pipeline_id}` }));
1829
+ return response.response.items.map((s) => ({
1830
+ name: s.name || `Stage ${s.id}`,
1831
+ value: s.id.toString(),
1832
+ description: `Pipeline ID: ${s.pipeline_id}`,
1833
+ }));
1483
1834
  }
1484
1835
  return [];
1485
1836
  }
@@ -1494,7 +1845,9 @@ class Flowlu {
1494
1845
  try {
1495
1846
  pipelineId = this.getNodeParameter('opportunityFilterPipeline');
1496
1847
  }
1497
- catch { /* not set yet */ }
1848
+ catch {
1849
+ /* not set yet */
1850
+ }
1498
1851
  const response = await flowluApiRequest.call(this, 'GET', baseUrl, '/api/v1/module/crm/pipeline_stage/list', apiKey);
1499
1852
  if (response?.response?.items) {
1500
1853
  let stages = response.response.items;
@@ -1530,7 +1883,10 @@ class Flowlu {
1530
1883
  const { baseUrl, apiKey } = await getFlowluCredentials(this);
1531
1884
  const response = await flowluApiRequest.call(this, 'GET', baseUrl, '/api/v1/module/crm/source/list', apiKey);
1532
1885
  if (response?.response?.items) {
1533
- return response.response.items.map((s) => ({ name: s.name || `Source ${s.id}`, value: s.id.toString() }));
1886
+ return response.response.items.map((s) => ({
1887
+ name: s.name || `Source ${s.id}`,
1888
+ value: s.id.toString(),
1889
+ }));
1534
1890
  }
1535
1891
  return [];
1536
1892
  }
@@ -1543,7 +1899,10 @@ class Flowlu {
1543
1899
  const { baseUrl, apiKey } = await getFlowluCredentials(this);
1544
1900
  const response = await flowluApiRequest.call(this, 'GET', baseUrl, '/api/v1/module/st/portfolio/list', apiKey);
1545
1901
  if (response?.response?.items) {
1546
- return response.response.items.map((p) => ({ name: p.name || `Portfolio ${p.id}`, value: p.id.toString() }));
1902
+ return response.response.items.map((p) => ({
1903
+ name: p.name || `Portfolio ${p.id}`,
1904
+ value: p.id.toString(),
1905
+ }));
1547
1906
  }
1548
1907
  return [];
1549
1908
  }
@@ -1556,7 +1915,10 @@ class Flowlu {
1556
1915
  const { baseUrl, apiKey } = await getFlowluCredentials(this);
1557
1916
  const response = await flowluApiRequest.call(this, 'GET', baseUrl, '/api/v1/module/st/stages/list', apiKey);
1558
1917
  if (response?.response?.items) {
1559
- return response.response.items.map((s) => ({ name: s.name || `Stage ${s.id}`, value: s.id.toString() }));
1918
+ return response.response.items.map((s) => ({
1919
+ name: s.name || `Stage ${s.id}`,
1920
+ value: s.id.toString(),
1921
+ }));
1560
1922
  }
1561
1923
  return [];
1562
1924
  }
@@ -1569,7 +1931,10 @@ class Flowlu {
1569
1931
  const { baseUrl, apiKey } = await getFlowluCredentials(this);
1570
1932
  const response = await flowluApiRequest.call(this, 'GET', baseUrl, '/api/v1/module/customlists/lists/list', apiKey);
1571
1933
  if (response?.response?.items) {
1572
- return response.response.items.map((l) => ({ name: l.name || `List ${l.id}`, value: l.id.toString() }));
1934
+ return response.response.items.map((l) => ({
1935
+ name: l.name || `List ${l.id}`,
1936
+ value: l.id.toString(),
1937
+ }));
1573
1938
  }
1574
1939
  return [];
1575
1940
  }
@@ -1611,7 +1976,7 @@ class Flowlu {
1611
1976
  .filter((f) => fieldsetIds.includes(f.fieldset_id?.toString()))
1612
1977
  .filter((f) => f.active !== 0)
1613
1978
  .map((f) => {
1614
- const cfKey = (f.api_use_alias && f.alias) ? `cf_${f.alias}` : `cf_${f.id}`;
1979
+ const cfKey = f.api_use_alias && f.alias ? `cf_${f.alias}` : `cf_${f.id}`;
1615
1980
  let label = f.name || cfKey;
1616
1981
  let desc = '';
1617
1982
  // Detect link fields (model.any) and show what they link to
@@ -1631,7 +1996,9 @@ class Flowlu {
1631
1996
  }
1632
1997
  else if (f.module === 'customlists' && f.model === 'items' && f.group_id) {
1633
1998
  // Link to another custom list - find its name
1634
- const targetList = allFieldsets.find((fs) => fs.module === 'customlists' && fs.model === 'items' && fs.group_id?.toString() === f.group_id.toString());
1999
+ const targetList = allFieldsets.find((fs) => fs.module === 'customlists' &&
2000
+ fs.model === 'items' &&
2001
+ fs.group_id?.toString() === f.group_id.toString());
1635
2002
  const listName = targetList?.name || `List #${f.group_id}`;
1636
2003
  label = `${f.name} → ${listName}`;
1637
2004
  desc = `Enter the Record ID from "${listName}"`;
@@ -1763,7 +2130,7 @@ class Flowlu {
1763
2130
  // Find the label field for this list
1764
2131
  const labelFieldId = f.group_label_field_id;
1765
2132
  linkOptionsCache[clKey] = (resp?.response?.items || []).map((item) => {
1766
- const label = labelFieldId ? (item[`cf_${labelFieldId}`] || `#${item.id}`) : `#${item.id}`;
2133
+ const label = labelFieldId ? item[`cf_${labelFieldId}`] || `#${item.id}` : `#${item.id}`;
1767
2134
  return { name: label, value: item.id };
1768
2135
  });
1769
2136
  }
@@ -1775,7 +2142,7 @@ class Flowlu {
1775
2142
  }
1776
2143
  }
1777
2144
  const fields = filteredFields.map((f) => {
1778
- const cfKey = (f.api_use_alias && f.alias) ? `cf_${f.alias}` : `cf_${f.id}`;
2145
+ const cfKey = f.api_use_alias && f.alias ? `cf_${f.alias}` : `cf_${f.id}`;
1779
2146
  let displayName = f.name || cfKey;
1780
2147
  let fieldType = 'string';
1781
2148
  let fieldOptions;
@@ -1797,7 +2164,9 @@ class Flowlu {
1797
2164
  .filter((o) => o.value)
1798
2165
  .map((o) => ({ name: o.value, value: o.id?.toString() || o.value }));
1799
2166
  }
1800
- catch { /* ignore parse errors */ }
2167
+ catch {
2168
+ /* ignore parse errors */
2169
+ }
1801
2170
  }
1802
2171
  // Link fields - use dropdown with fetched options
1803
2172
  if (f.type === 'model.any' && f.module && f.model) {
@@ -1806,12 +2175,12 @@ class Flowlu {
1806
2175
  displayName = `${f.name} → ${linkLabels[key]}`;
1807
2176
  }
1808
2177
  else if (f.module === 'customlists' && f.model === 'items' && f.group_id) {
1809
- const targetList = allFieldsets.find((fs) => fs.module === 'customlists' && fs.model === 'items' && fs.group_id?.toString() === f.group_id.toString());
2178
+ const targetList = allFieldsets.find((fs) => fs.module === 'customlists' &&
2179
+ fs.model === 'items' &&
2180
+ fs.group_id?.toString() === f.group_id.toString());
1810
2181
  displayName = `${f.name} → ${targetList?.name || `List #${f.group_id}`}`;
1811
2182
  }
1812
- const cacheKey = (f.module === 'customlists' && f.model === 'items' && f.group_id)
1813
- ? `customlists/${f.group_id}`
1814
- : key;
2183
+ const cacheKey = f.module === 'customlists' && f.model === 'items' && f.group_id ? `customlists/${f.group_id}` : key;
1815
2184
  if (linkOptionsCache[cacheKey]?.length) {
1816
2185
  fieldType = 'options';
1817
2186
  fieldOptions = linkOptionsCache[cacheKey];
@@ -1869,15 +2238,32 @@ class Flowlu {
1869
2238
  body.phone = phone;
1870
2239
  const additional = this.getNodeParameter('contactAdditionalFields', i);
1871
2240
  const contactSimpleFields = [
1872
- 'middle_name', 'description', 'owner_id', 'web',
1873
- 'phone2', 'phone3', 'email_personal',
1874
- 'social_network_link_1', 'social_network_link_2',
1875
- 'social_network_link_3', 'social_network_link_4',
1876
- 'social_network_link_5', 'social_network_link_6',
1877
- 'address', 'shipping_address_line_1', 'shipping_city',
1878
- 'shipping_state', 'shipping_zip', 'shipping_country',
1879
- 'billing_address_line_1', 'billing_city', 'billing_state',
1880
- 'billing_zip', 'billing_country', 'VAT', 'timezone',
2241
+ 'middle_name',
2242
+ 'description',
2243
+ 'owner_id',
2244
+ 'web',
2245
+ 'phone2',
2246
+ 'phone3',
2247
+ 'email_personal',
2248
+ 'social_network_link_1',
2249
+ 'social_network_link_2',
2250
+ 'social_network_link_3',
2251
+ 'social_network_link_4',
2252
+ 'social_network_link_5',
2253
+ 'social_network_link_6',
2254
+ 'address',
2255
+ 'shipping_address_line_1',
2256
+ 'shipping_city',
2257
+ 'shipping_state',
2258
+ 'shipping_zip',
2259
+ 'shipping_country',
2260
+ 'billing_address_line_1',
2261
+ 'billing_city',
2262
+ 'billing_state',
2263
+ 'billing_zip',
2264
+ 'billing_country',
2265
+ 'VAT',
2266
+ 'timezone',
1881
2267
  ];
1882
2268
  for (const field of contactSimpleFields) {
1883
2269
  if (additional[field] !== undefined && additional[field] !== '') {
@@ -1910,7 +2296,7 @@ class Flowlu {
1910
2296
  if (filters.owner_id)
1911
2297
  qs['filter[owner_id]'] = filters.owner_id;
1912
2298
  responseData = await flowluApiRequest.call(this, 'GET', baseUrl, '/api/v1/module/crm/account/list', apiKey, undefined, qs);
1913
- for (const item of (responseData?.response?.items || [])) {
2299
+ for (const item of responseData?.response?.items || []) {
1914
2300
  returnData.push({ json: item });
1915
2301
  }
1916
2302
  continue;
@@ -1920,13 +2306,25 @@ class Flowlu {
1920
2306
  const updateFields = this.getNodeParameter('contactUpdateFields', i);
1921
2307
  const body = { id };
1922
2308
  const contactUpdateSimpleFields = [
1923
- 'first_name', 'last_name', 'middle_name', 'email', 'phone',
1924
- 'phone2', 'phone3', 'description', 'owner_id', 'web',
2309
+ 'first_name',
2310
+ 'last_name',
2311
+ 'middle_name',
2312
+ 'email',
2313
+ 'phone',
2314
+ 'phone2',
2315
+ 'phone3',
2316
+ 'description',
2317
+ 'owner_id',
2318
+ 'web',
1925
2319
  'email_personal',
1926
- 'social_network_link_1', 'social_network_link_2',
1927
- 'social_network_link_3', 'social_network_link_4',
1928
- 'social_network_link_5', 'social_network_link_6',
1929
- 'address', 'VAT',
2320
+ 'social_network_link_1',
2321
+ 'social_network_link_2',
2322
+ 'social_network_link_3',
2323
+ 'social_network_link_4',
2324
+ 'social_network_link_5',
2325
+ 'social_network_link_6',
2326
+ 'address',
2327
+ 'VAT',
1930
2328
  ];
1931
2329
  for (const field of contactUpdateSimpleFields) {
1932
2330
  if (updateFields[field] !== undefined && updateFields[field] !== '') {
@@ -1962,9 +2360,16 @@ class Flowlu {
1962
2360
  body.assignee_id = assignee;
1963
2361
  const additional = this.getNodeParameter('opportunityAdditionalFields', i);
1964
2362
  const oppSimpleFields = [
1965
- 'budget', 'description', 'contact_name', 'contact_email',
1966
- 'contact_phone', 'contact_mobile', 'contact_company',
1967
- 'contact_position', 'contact_web', 'source_id',
2363
+ 'budget',
2364
+ 'description',
2365
+ 'contact_name',
2366
+ 'contact_email',
2367
+ 'contact_phone',
2368
+ 'contact_mobile',
2369
+ 'contact_company',
2370
+ 'contact_position',
2371
+ 'contact_web',
2372
+ 'source_id',
1968
2373
  ];
1969
2374
  for (const field of oppSimpleFields) {
1970
2375
  if (additional[field] !== undefined && additional[field] !== '') {
@@ -2022,7 +2427,7 @@ class Flowlu {
2022
2427
  if (filters.active !== undefined)
2023
2428
  qs['filter[active]'] = filters.active.toString();
2024
2429
  responseData = await flowluApiRequest.call(this, 'GET', baseUrl, '/api/v1/module/crm/lead/list', apiKey, undefined, qs);
2025
- for (const item of (responseData?.response?.items || [])) {
2430
+ for (const item of responseData?.response?.items || []) {
2026
2431
  returnData.push({ json: item });
2027
2432
  }
2028
2433
  continue;
@@ -2032,9 +2437,17 @@ class Flowlu {
2032
2437
  const updateFields = this.getNodeParameter('opportunityUpdateFields', i);
2033
2438
  const body = { id };
2034
2439
  const oppUpdateFields = [
2035
- 'name', 'pipeline_id', 'pipeline_stage_id', 'assignee_id',
2036
- 'budget', 'description', 'active', 'closing_comment',
2037
- 'contact_name', 'contact_email', 'contact_phone',
2440
+ 'name',
2441
+ 'pipeline_id',
2442
+ 'pipeline_stage_id',
2443
+ 'assignee_id',
2444
+ 'budget',
2445
+ 'description',
2446
+ 'active',
2447
+ 'closing_comment',
2448
+ 'contact_name',
2449
+ 'contact_email',
2450
+ 'contact_phone',
2038
2451
  ];
2039
2452
  for (const field of oppUpdateFields) {
2040
2453
  if (updateFields[field] !== undefined && updateFields[field] !== '') {
@@ -2077,9 +2490,16 @@ class Flowlu {
2077
2490
  body.description = desc;
2078
2491
  const additional = this.getNodeParameter('projectAdditionalFields', i);
2079
2492
  const projSimpleFields = [
2080
- 'priority', 'estimated_revenue', 'estimated_expenses',
2081
- 'customer_id', 'customer_crm_contact_id', 'briefcase_id',
2082
- 'stage_id', 'tasks_workflow_id', 'billing_type', 'crm_lead_id',
2493
+ 'priority',
2494
+ 'estimated_revenue',
2495
+ 'estimated_expenses',
2496
+ 'customer_id',
2497
+ 'customer_crm_contact_id',
2498
+ 'briefcase_id',
2499
+ 'stage_id',
2500
+ 'tasks_workflow_id',
2501
+ 'billing_type',
2502
+ 'crm_lead_id',
2083
2503
  ];
2084
2504
  for (const field of projSimpleFields) {
2085
2505
  if (additional[field] !== undefined && additional[field] !== '' && additional[field] !== 0) {
@@ -2115,7 +2535,7 @@ class Flowlu {
2115
2535
  if (!filters.is_archive)
2116
2536
  qs['filter[is_archive]'] = '0';
2117
2537
  responseData = await flowluApiRequest.call(this, 'GET', baseUrl, '/api/v1/module/st/projects/list', apiKey, undefined, qs);
2118
- for (const item of (responseData?.response?.items || [])) {
2538
+ for (const item of responseData?.response?.items || []) {
2119
2539
  returnData.push({ json: item });
2120
2540
  }
2121
2541
  continue;
@@ -2125,8 +2545,13 @@ class Flowlu {
2125
2545
  const updateFields = this.getNodeParameter('projectUpdateFields', i);
2126
2546
  const body = { id };
2127
2547
  const projUpdateFields = [
2128
- 'name', 'description', 'manager_id', 'priority',
2129
- 'estimated_revenue', 'estimated_expenses', 'stage_id',
2548
+ 'name',
2549
+ 'description',
2550
+ 'manager_id',
2551
+ 'priority',
2552
+ 'estimated_revenue',
2553
+ 'estimated_expenses',
2554
+ 'stage_id',
2130
2555
  ];
2131
2556
  for (const field of projUpdateFields) {
2132
2557
  if (updateFields[field] !== undefined && updateFields[field] !== '') {
@@ -2179,7 +2604,7 @@ class Flowlu {
2179
2604
  if (filters.search)
2180
2605
  qs['search'] = filters.search;
2181
2606
  responseData = await flowluApiRequest.call(this, 'GET', baseUrl, '/api/v1/module/customlists/items/list', apiKey, undefined, qs);
2182
- for (const item of (responseData?.response?.items || [])) {
2607
+ for (const item of responseData?.response?.items || []) {
2183
2608
  returnData.push({ json: item });
2184
2609
  }
2185
2610
  continue;
@@ -2278,7 +2703,7 @@ class Flowlu {
2278
2703
  if (filters.status !== undefined)
2279
2704
  qs['filter[status]'] = filters.status.toString();
2280
2705
  responseData = await flowluApiRequest.call(this, 'GET', baseUrl, '/api/v1/module/task/tasks/list', apiKey, undefined, qs);
2281
- for (const item of (responseData?.response?.items || [])) {
2706
+ for (const item of responseData?.response?.items || []) {
2282
2707
  returnData.push({ json: item });
2283
2708
  }
2284
2709
  continue;
@@ -2349,14 +2774,14 @@ class Flowlu {
2349
2774
  const entityType = this.getNodeParameter('tagEntityType', i);
2350
2775
  const entityId = this.getNodeParameter('tagEntityId', i);
2351
2776
  responseData = await flowluApiRequest.call(this, 'GET', baseUrl, `/api/v1/module/${entityType}/${entityId}/global_tags/list`, apiKey);
2352
- for (const item of (responseData?.response?.items || [])) {
2777
+ for (const item of responseData?.response?.items || []) {
2353
2778
  returnData.push({ json: item });
2354
2779
  }
2355
2780
  continue;
2356
2781
  }
2357
2782
  else if (operation === 'listAll') {
2358
2783
  responseData = await flowluApiRequest.call(this, 'GET', baseUrl, '/api/v1/module/core/tag/list', apiKey);
2359
- for (const item of (responseData?.response?.items || [])) {
2784
+ for (const item of responseData?.response?.items || []) {
2360
2785
  returnData.push({ json: item });
2361
2786
  }
2362
2787
  continue;
@@ -2387,7 +2812,7 @@ class Flowlu {
2387
2812
  const entityId = this.getNodeParameter('commentEntityId', i);
2388
2813
  const limit = this.getNodeParameter('limit', i);
2389
2814
  responseData = await flowluApiRequest.call(this, 'GET', baseUrl, `/api/v1/module/${entityType}/${entityId}/comments/list`, apiKey, undefined, { limit: limit.toString() });
2390
- for (const item of (responseData?.response?.items || [])) {
2815
+ for (const item of responseData?.response?.items || []) {
2391
2816
  returnData.push({ json: item });
2392
2817
  }
2393
2818
  continue;