n8n-nodes-steyi-ss 1.0.2 → 1.0.4
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.
- package/README.md +73 -17
- package/dist/nodes/SteyiSmartsheet/SteyiSmartsheet.node.js +168 -24
- package/dist/nodes/SteyiSmartsheet/SteyiSmartsheetApi.js +1 -1
- package/dist/nodes/SteyiSmartsheet/executors/Admin.js +3 -3
- package/dist/nodes/SteyiSmartsheet/executors/Converter.d.ts +2 -0
- package/dist/nodes/SteyiSmartsheet/executors/Converter.js +51 -0
- package/dist/nodes/SteyiSmartsheet/executors/Rows.js +366 -42
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -199,17 +199,65 @@ Add a new row to a sheet:
|
|
|
199
199
|
- Attachment category (Regular Attachment or Proof)
|
|
200
200
|
- Custom filename
|
|
201
201
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
-
|
|
212
|
-
-
|
|
202
|
+
## Column Value Formatting
|
|
203
|
+
|
|
204
|
+
When adding or updating rows, different column types require specific value formats:
|
|
205
|
+
|
|
206
|
+
### TEXT_NUMBER, DATE, DATETIME
|
|
207
|
+
- **Format**: Plain text or number
|
|
208
|
+
- **Example**: `"John Doe"`, `123`, `"2024-01-15"`
|
|
209
|
+
|
|
210
|
+
### CHECKBOX
|
|
211
|
+
- **Format**: String values that are auto-converted to boolean
|
|
212
|
+
- **Accepted values**: `"true"`, `"false"`, `"1"`, `"0"`, `"yes"`, `"no"` (case-insensitive)
|
|
213
|
+
- **Example**: `"true"` → `true`, `"false"` → `false`
|
|
214
|
+
- The node automatically converts these strings to boolean values
|
|
215
|
+
|
|
216
|
+
### PICKLIST
|
|
217
|
+
- **Format**: Option text (must match exactly, case-sensitive)
|
|
218
|
+
- **Example**: `"High Priority"` (must match an option defined in the column)
|
|
219
|
+
|
|
220
|
+
### MULTI_CONTACT_LIST
|
|
221
|
+
- **Format**: JSON object with `values` array containing email objects
|
|
222
|
+
- **Example**:
|
|
223
|
+
```json
|
|
224
|
+
{
|
|
225
|
+
"values": [
|
|
226
|
+
{ "email": "john.smith@example.com" },
|
|
227
|
+
{ "email": "jane.doe@example.com" }
|
|
228
|
+
]
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
- The node automatically transforms this to the correct Smartsheet API format:
|
|
232
|
+
```json
|
|
233
|
+
{
|
|
234
|
+
"objectType": "MULTI_CONTACT",
|
|
235
|
+
"values": [
|
|
236
|
+
{ "objectType": "CONTACT", "email": "john.smith@example.com" },
|
|
237
|
+
{ "objectType": "CONTACT", "email": "jane.doe@example.com" }
|
|
238
|
+
]
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### MULTI_PICKLIST
|
|
243
|
+
- **Format**: JSON object with `values` array containing option strings
|
|
244
|
+
- **Example**:
|
|
245
|
+
```json
|
|
246
|
+
{
|
|
247
|
+
"values": [
|
|
248
|
+
"Option 1",
|
|
249
|
+
"Option 2"
|
|
250
|
+
]
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
- **Important**: Option values must match exactly (case-sensitive) the options defined in the MULTI_PICKLIST column
|
|
254
|
+
- The node automatically transforms this to the correct Smartsheet API format:
|
|
255
|
+
```json
|
|
256
|
+
{
|
|
257
|
+
"objectType": "MULTI_PICKLIST",
|
|
258
|
+
"values": ["Option 1", "Option 2"]
|
|
259
|
+
}
|
|
260
|
+
```
|
|
213
261
|
|
|
214
262
|
#### Update Row
|
|
215
263
|
Update an existing row with the same options as Add Row:
|
|
@@ -413,15 +461,23 @@ For the trigger node, n8n automatically generates the webhook URL, but it must b
|
|
|
413
461
|
|
|
414
462
|
### Multi-Contact List Support
|
|
415
463
|
The node automatically handles `MULTI_CONTACT_LIST` columns by:
|
|
416
|
-
-
|
|
417
|
-
-
|
|
418
|
-
-
|
|
464
|
+
- Accepting JSON format: `{ "values": [{ "email": "..." }, ...] }`
|
|
465
|
+
- Automatically adding `objectType: "MULTI_CONTACT"` to the objectValue
|
|
466
|
+
- Wrapping each contact with `objectType: "CONTACT"` in the values array
|
|
467
|
+
- Validating email format and structure
|
|
419
468
|
|
|
420
469
|
### Multi-Picklist Support
|
|
421
470
|
The node handles `MULTI_PICKLIST` columns by:
|
|
422
|
-
-
|
|
423
|
-
-
|
|
424
|
-
-
|
|
471
|
+
- Accepting JSON format: `{ "values": ["Option 1", "Option 2"] }`
|
|
472
|
+
- Automatically adding `objectType: "MULTI_PICKLIST"` to the objectValue
|
|
473
|
+
- Keeping values as strings (not wrapped in objects)
|
|
474
|
+
- Validating that option values match column options (case-sensitive)
|
|
475
|
+
|
|
476
|
+
### Checkbox Support
|
|
477
|
+
The node automatically handles `CHECKBOX` columns by:
|
|
478
|
+
- Converting string values to boolean: `"true"`, `"false"`, `"1"`, `"0"`, `"yes"`, `"no"`
|
|
479
|
+
- Case-insensitive conversion
|
|
480
|
+
- Empty values default to `false`
|
|
425
481
|
|
|
426
482
|
### Attachment Handling
|
|
427
483
|
- **File Uploads**: Supports binary data from n8n's binary data system
|
|
@@ -1,4 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
26
|
exports.SteyiSmartsheet = void 0;
|
|
4
27
|
const Sheets_1 = require("./executors/Sheets");
|
|
@@ -7,6 +30,7 @@ const Webhooks_1 = require("./executors/Webhooks");
|
|
|
7
30
|
const Columns_1 = require("./executors/Columns");
|
|
8
31
|
const Reports_1 = require("./executors/Reports");
|
|
9
32
|
const Admin_1 = require("./executors/Admin");
|
|
33
|
+
const Converter_1 = require("./executors/Converter");
|
|
10
34
|
const SteyiSmartsheetApi_1 = require("./SteyiSmartsheetApi");
|
|
11
35
|
const SteyiGenericFunction_1 = require("./SteyiGenericFunction");
|
|
12
36
|
class SteyiSmartsheet {
|
|
@@ -67,6 +91,11 @@ class SteyiSmartsheet {
|
|
|
67
91
|
value: 'admin',
|
|
68
92
|
description: 'Manage users, groups, and group members',
|
|
69
93
|
},
|
|
94
|
+
{
|
|
95
|
+
name: 'Converter',
|
|
96
|
+
value: 'converter',
|
|
97
|
+
description: 'Utility tools for data conversion',
|
|
98
|
+
},
|
|
70
99
|
],
|
|
71
100
|
default: 'sheet',
|
|
72
101
|
required: true,
|
|
@@ -571,7 +600,7 @@ class SteyiSmartsheet {
|
|
|
571
600
|
},
|
|
572
601
|
},
|
|
573
602
|
default: '',
|
|
574
|
-
description: 'Select a column',
|
|
603
|
+
description: 'Select a column. The column type is shown in parentheses next to each column name (e.g., "Column Name (MULTI_CONTACT_LIST)")',
|
|
575
604
|
},
|
|
576
605
|
{
|
|
577
606
|
displayName: 'Column ID',
|
|
@@ -588,9 +617,9 @@ class SteyiSmartsheet {
|
|
|
588
617
|
{
|
|
589
618
|
displayName: 'Value',
|
|
590
619
|
name: 'value',
|
|
591
|
-
type: '
|
|
620
|
+
type: 'json',
|
|
592
621
|
default: '',
|
|
593
|
-
description: 'The value to set',
|
|
622
|
+
description: 'The value to set. Column type is shown in parentheses in the dropdown above. For MULTI_CONTACT_LIST and MULTI_PICKLIST columns, enter JSON format. For other columns, enter plain text/number. For format examples, see the <a href="https://www.npmjs.com/package/n8n-nodes-steyi-ss" target="_blank">npm package README</a>.',
|
|
594
623
|
},
|
|
595
624
|
],
|
|
596
625
|
},
|
|
@@ -1529,13 +1558,9 @@ class SteyiSmartsheet {
|
|
|
1529
1558
|
type: 'options',
|
|
1530
1559
|
displayOptions: {
|
|
1531
1560
|
show: {
|
|
1532
|
-
resource: ['admin'],
|
|
1533
|
-
operation: ['group', 'groupMember'],
|
|
1534
|
-
},
|
|
1535
|
-
hide: {
|
|
1536
1561
|
resource: ['admin'],
|
|
1537
1562
|
operation: ['group'],
|
|
1538
|
-
groupOperation: ['
|
|
1563
|
+
groupOperation: ['getGroup', 'updateGroup', 'deleteGroup'],
|
|
1539
1564
|
},
|
|
1540
1565
|
},
|
|
1541
1566
|
options: [
|
|
@@ -1562,14 +1587,10 @@ class SteyiSmartsheet {
|
|
|
1562
1587
|
},
|
|
1563
1588
|
displayOptions: {
|
|
1564
1589
|
show: {
|
|
1565
|
-
resource: ['admin'],
|
|
1566
|
-
operation: ['group', 'groupMember'],
|
|
1567
|
-
groupInputMethod: ['list'],
|
|
1568
|
-
},
|
|
1569
|
-
hide: {
|
|
1570
1590
|
resource: ['admin'],
|
|
1571
1591
|
operation: ['group'],
|
|
1572
|
-
groupOperation: ['
|
|
1592
|
+
groupOperation: ['getGroup', 'updateGroup', 'deleteGroup'],
|
|
1593
|
+
groupInputMethod: ['list'],
|
|
1573
1594
|
},
|
|
1574
1595
|
},
|
|
1575
1596
|
default: '',
|
|
@@ -1583,13 +1604,66 @@ class SteyiSmartsheet {
|
|
|
1583
1604
|
displayOptions: {
|
|
1584
1605
|
show: {
|
|
1585
1606
|
resource: ['admin'],
|
|
1586
|
-
operation: ['group'
|
|
1607
|
+
operation: ['group'],
|
|
1608
|
+
groupOperation: ['getGroup', 'updateGroup', 'deleteGroup'],
|
|
1587
1609
|
groupInputMethod: ['id'],
|
|
1588
1610
|
},
|
|
1589
|
-
|
|
1611
|
+
},
|
|
1612
|
+
default: '',
|
|
1613
|
+
required: true,
|
|
1614
|
+
},
|
|
1615
|
+
{
|
|
1616
|
+
displayName: 'Group Input Method',
|
|
1617
|
+
name: 'groupMemberGroupInputMethod',
|
|
1618
|
+
type: 'options',
|
|
1619
|
+
displayOptions: {
|
|
1620
|
+
show: {
|
|
1590
1621
|
resource: ['admin'],
|
|
1591
|
-
operation: ['
|
|
1592
|
-
|
|
1622
|
+
operation: ['groupMember'],
|
|
1623
|
+
},
|
|
1624
|
+
},
|
|
1625
|
+
options: [
|
|
1626
|
+
{
|
|
1627
|
+
name: 'Select from List',
|
|
1628
|
+
value: 'list',
|
|
1629
|
+
},
|
|
1630
|
+
{
|
|
1631
|
+
name: 'Enter Group ID',
|
|
1632
|
+
value: 'id',
|
|
1633
|
+
},
|
|
1634
|
+
],
|
|
1635
|
+
default: 'list',
|
|
1636
|
+
description: 'Choose how to specify the group',
|
|
1637
|
+
},
|
|
1638
|
+
{
|
|
1639
|
+
displayName: 'Group',
|
|
1640
|
+
name: 'groupMemberGroupId',
|
|
1641
|
+
type: 'options',
|
|
1642
|
+
description: 'Select a group from the list',
|
|
1643
|
+
typeOptions: {
|
|
1644
|
+
loadOptionsMethod: 'getGroups',
|
|
1645
|
+
searchable: true,
|
|
1646
|
+
},
|
|
1647
|
+
displayOptions: {
|
|
1648
|
+
show: {
|
|
1649
|
+
resource: ['admin'],
|
|
1650
|
+
operation: ['groupMember'],
|
|
1651
|
+
groupMemberGroupInputMethod: ['list'],
|
|
1652
|
+
},
|
|
1653
|
+
},
|
|
1654
|
+
default: '',
|
|
1655
|
+
required: true,
|
|
1656
|
+
},
|
|
1657
|
+
{
|
|
1658
|
+
displayName: 'Group ID',
|
|
1659
|
+
name: 'groupMemberGroupIdManual',
|
|
1660
|
+
type: 'string',
|
|
1661
|
+
description: 'Enter the Group ID manually',
|
|
1662
|
+
displayOptions: {
|
|
1663
|
+
show: {
|
|
1664
|
+
resource: ['admin'],
|
|
1665
|
+
operation: ['groupMember'],
|
|
1666
|
+
groupMemberGroupInputMethod: ['id'],
|
|
1593
1667
|
},
|
|
1594
1668
|
},
|
|
1595
1669
|
default: '',
|
|
@@ -1749,6 +1823,46 @@ class SteyiSmartsheet {
|
|
|
1749
1823
|
default: '',
|
|
1750
1824
|
required: true,
|
|
1751
1825
|
},
|
|
1826
|
+
{
|
|
1827
|
+
displayName: 'Operation',
|
|
1828
|
+
name: 'operation',
|
|
1829
|
+
type: 'options',
|
|
1830
|
+
noDataExpression: true,
|
|
1831
|
+
displayOptions: {
|
|
1832
|
+
show: {
|
|
1833
|
+
resource: ['converter'],
|
|
1834
|
+
},
|
|
1835
|
+
},
|
|
1836
|
+
options: [
|
|
1837
|
+
{
|
|
1838
|
+
name: 'CSV to MCL Format',
|
|
1839
|
+
value: 'csvToMclFormat',
|
|
1840
|
+
description: 'Convert comma-separated email values to MULTI_CONTACT_LIST format',
|
|
1841
|
+
action: 'Convert CSV to MCL format',
|
|
1842
|
+
},
|
|
1843
|
+
{
|
|
1844
|
+
name: 'CSV to MPL',
|
|
1845
|
+
value: 'csvToMplFormat',
|
|
1846
|
+
description: 'Convert comma-separated values to MULTI_PICKLIST format',
|
|
1847
|
+
action: 'Convert CSV to MPL format',
|
|
1848
|
+
},
|
|
1849
|
+
],
|
|
1850
|
+
default: 'csvToMclFormat',
|
|
1851
|
+
},
|
|
1852
|
+
{
|
|
1853
|
+
displayName: 'CSV Values',
|
|
1854
|
+
name: 'csvValues',
|
|
1855
|
+
type: 'string',
|
|
1856
|
+
displayOptions: {
|
|
1857
|
+
show: {
|
|
1858
|
+
resource: ['converter'],
|
|
1859
|
+
operation: ['csvToMclFormat', 'csvToMplFormat'],
|
|
1860
|
+
},
|
|
1861
|
+
},
|
|
1862
|
+
default: '',
|
|
1863
|
+
required: true,
|
|
1864
|
+
description: 'Comma-separated values (e.g., "email1@example.com, email2@example.com" for MCL or "Option 1, Option 2" for MPL)',
|
|
1865
|
+
},
|
|
1752
1866
|
],
|
|
1753
1867
|
};
|
|
1754
1868
|
this.methods = {
|
|
@@ -1768,14 +1882,40 @@ class SteyiSmartsheet {
|
|
|
1768
1882
|
if (sheetId === undefined || sheetId === null || sheetId === '') {
|
|
1769
1883
|
return [];
|
|
1770
1884
|
}
|
|
1771
|
-
|
|
1772
|
-
|
|
1885
|
+
// Get columns with level=2 to ensure we get the correct column types
|
|
1886
|
+
let columns = [];
|
|
1887
|
+
try {
|
|
1888
|
+
const columnsResponse = await SteyiSmartsheetApi_1.listColumns.call(this, parseInt(sheetId.toString()));
|
|
1889
|
+
if (columnsResponse && columnsResponse.data && Array.isArray(columnsResponse.data)) {
|
|
1890
|
+
columns = columnsResponse.data;
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
catch (error) {
|
|
1894
|
+
// If columns endpoint fails, try getting the sheet with columns included and level=2
|
|
1895
|
+
try {
|
|
1896
|
+
const { smartsheetApiRequest } = await Promise.resolve().then(() => __importStar(require('./SteyiGenericFunction')));
|
|
1897
|
+
const sheetResponse = await smartsheetApiRequest.call(this, 'GET', `/sheets/${sheetId}?include=columns&level=2`, {}, 0);
|
|
1898
|
+
if (sheetResponse && sheetResponse.columns && Array.isArray(sheetResponse.columns)) {
|
|
1899
|
+
columns = sheetResponse.columns;
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
catch (sheetError) {
|
|
1903
|
+
// If both fail, return empty array
|
|
1904
|
+
return [];
|
|
1905
|
+
}
|
|
1906
|
+
}
|
|
1907
|
+
if (columns.length === 0) {
|
|
1773
1908
|
return [];
|
|
1774
1909
|
}
|
|
1775
|
-
return columns.
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1910
|
+
return columns.map((column) => {
|
|
1911
|
+
// The type field should be present in the API response with level=2
|
|
1912
|
+
const columnType = column.type || 'UNKNOWN';
|
|
1913
|
+
return {
|
|
1914
|
+
name: `${column.title} (${columnType})`,
|
|
1915
|
+
value: column.id.toString(),
|
|
1916
|
+
description: `Type: ${columnType}`,
|
|
1917
|
+
};
|
|
1918
|
+
});
|
|
1779
1919
|
},
|
|
1780
1920
|
async getDiscussions() {
|
|
1781
1921
|
const sheetId = this.getNodeParameter('sheetId', 0);
|
|
@@ -1967,6 +2107,10 @@ class SteyiSmartsheet {
|
|
|
1967
2107
|
const result = await Admin_1.executeAdminOperation.call(this, operation, i);
|
|
1968
2108
|
returnData.push(result);
|
|
1969
2109
|
}
|
|
2110
|
+
else if (resource === 'converter') {
|
|
2111
|
+
const result = await Converter_1.executeConverterOperation.call(this, operation, i);
|
|
2112
|
+
returnData.push(result);
|
|
2113
|
+
}
|
|
1970
2114
|
else {
|
|
1971
2115
|
throw new Error(`Unknown resource: ${resource}`);
|
|
1972
2116
|
}
|
|
@@ -24,7 +24,7 @@ async function listSheets(includeAll = true) {
|
|
|
24
24
|
}
|
|
25
25
|
exports.listSheets = listSheets;
|
|
26
26
|
async function listColumns(sheetId) {
|
|
27
|
-
return await SteyiGenericFunction_1.smartsheetApiRequest.call(this, 'GET', `/sheets/${sheetId}/columns`, {}, 0);
|
|
27
|
+
return await SteyiGenericFunction_1.smartsheetApiRequest.call(this, 'GET', `/sheets/${sheetId}/columns?level=2`, {}, 0);
|
|
28
28
|
}
|
|
29
29
|
exports.listColumns = listColumns;
|
|
30
30
|
async function listWebhooks() {
|
|
@@ -132,10 +132,10 @@ async function executeAdminOperation(operation, itemIndex) {
|
|
|
132
132
|
}
|
|
133
133
|
case 'groupMember': {
|
|
134
134
|
const groupMemberOperation = this.getNodeParameter('groupMemberOperation', itemIndex);
|
|
135
|
-
const groupInputMethod = this.getNodeParameter('
|
|
135
|
+
const groupInputMethod = this.getNodeParameter('groupMemberGroupInputMethod', itemIndex, 'list');
|
|
136
136
|
const groupId = groupInputMethod === 'id'
|
|
137
|
-
? this.getNodeParameter('
|
|
138
|
-
: this.getNodeParameter('
|
|
137
|
+
? this.getNodeParameter('groupMemberGroupIdManual', itemIndex)
|
|
138
|
+
: this.getNodeParameter('groupMemberGroupId', itemIndex);
|
|
139
139
|
switch (groupMemberOperation) {
|
|
140
140
|
case 'listGroupMembers': {
|
|
141
141
|
responseData = await SteyiSmartsheetApi_1.listGroupMembers.call(this, parseInt(groupId.toString()));
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.executeConverterOperation = void 0;
|
|
4
|
+
async function executeConverterOperation(operation, itemIndex) {
|
|
5
|
+
switch (operation) {
|
|
6
|
+
case 'csvToMclFormat': {
|
|
7
|
+
const emailsRaw = this.getNodeParameter('csvValues', itemIndex);
|
|
8
|
+
if (!emailsRaw || typeof emailsRaw !== 'string') {
|
|
9
|
+
throw new Error('CSV values input is required and must be a string');
|
|
10
|
+
}
|
|
11
|
+
// Split by comma, trim whitespace, filter out empty strings, and map to email objects
|
|
12
|
+
const values = emailsRaw
|
|
13
|
+
.split(',')
|
|
14
|
+
.map(e => e.trim())
|
|
15
|
+
.filter(e => e.length > 0)
|
|
16
|
+
.map(email => ({ email }));
|
|
17
|
+
// Return as an object with mcl-output property containing values
|
|
18
|
+
return {
|
|
19
|
+
json: {
|
|
20
|
+
'mcl-output': {
|
|
21
|
+
values: values,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
pairedItem: { item: itemIndex },
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
case 'csvToMplFormat': {
|
|
28
|
+
const optionsRaw = this.getNodeParameter('csvValues', itemIndex);
|
|
29
|
+
if (!optionsRaw || typeof optionsRaw !== 'string') {
|
|
30
|
+
throw new Error('CSV values input is required and must be a string');
|
|
31
|
+
}
|
|
32
|
+
// Split by comma, trim whitespace, filter out empty strings (returns array of strings)
|
|
33
|
+
const values = optionsRaw
|
|
34
|
+
.split(',')
|
|
35
|
+
.map(e => e.trim())
|
|
36
|
+
.filter(e => e.length > 0);
|
|
37
|
+
// Return as an object with mpl-output property containing values array
|
|
38
|
+
return {
|
|
39
|
+
json: {
|
|
40
|
+
'mpl-output': {
|
|
41
|
+
values: values,
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
pairedItem: { item: itemIndex },
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
default:
|
|
48
|
+
throw new Error(`Unknown converter operation: ${operation}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.executeConverterOperation = executeConverterOperation;
|
|
@@ -163,7 +163,14 @@ async function executeRowOperation(operation, itemIndex) {
|
|
|
163
163
|
catch (error) {
|
|
164
164
|
// If we can't get columns, continue without column type info
|
|
165
165
|
}
|
|
166
|
-
|
|
166
|
+
// Filter out any cells with empty columnId or invalid data
|
|
167
|
+
const validCells = (cellsData.cell || []).filter((cell) => {
|
|
168
|
+
const columnId = cell.columnInputMethod === 'id'
|
|
169
|
+
? cell.columnIdManual
|
|
170
|
+
: cell.columnId;
|
|
171
|
+
return columnId && columnId !== '' && cell.value !== undefined;
|
|
172
|
+
});
|
|
173
|
+
const cells = validCells.map((cell) => {
|
|
167
174
|
let columnId;
|
|
168
175
|
if (cell.columnInputMethod === 'id') {
|
|
169
176
|
columnId = cell.columnIdManual || '';
|
|
@@ -171,7 +178,11 @@ async function executeRowOperation(operation, itemIndex) {
|
|
|
171
178
|
else {
|
|
172
179
|
columnId = cell.columnId || '';
|
|
173
180
|
}
|
|
181
|
+
// Parse columnId - keep as number for API, but ensure it's valid
|
|
174
182
|
const colIdNum = parseInt(columnId, 10);
|
|
183
|
+
if (isNaN(colIdNum)) {
|
|
184
|
+
throw new Error(`Invalid column ID: ${columnId}`);
|
|
185
|
+
}
|
|
175
186
|
const column = columnsMap.get(colIdNum);
|
|
176
187
|
const columnType = column?.type;
|
|
177
188
|
// Clean up the value - remove surrounding quotes if present
|
|
@@ -185,37 +196,188 @@ async function executeRowOperation(operation, itemIndex) {
|
|
|
185
196
|
}
|
|
186
197
|
}
|
|
187
198
|
// Handle MULTI_CONTACT_LIST and MULTI_PICKLIST columns with objectValue
|
|
188
|
-
// User
|
|
189
|
-
if (columnType === 'MULTI_CONTACT_LIST'
|
|
190
|
-
// Parse the value as JSON
|
|
191
|
-
let
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
199
|
+
// User provides a JSON object (field type is 'json' so n8n parses it automatically)
|
|
200
|
+
if (columnType === 'MULTI_CONTACT_LIST') {
|
|
201
|
+
// Parse the value - if it's a string, try to parse as JSON; if already an object, use it directly
|
|
202
|
+
let parsedValue;
|
|
203
|
+
if (typeof cellValue === 'string') {
|
|
204
|
+
try {
|
|
205
|
+
parsedValue = JSON.parse(cellValue);
|
|
206
|
+
}
|
|
207
|
+
catch (error) {
|
|
208
|
+
throw new Error(`Invalid JSON for MULTI_CONTACT_LIST column (Column ID: ${colIdNum}). ` +
|
|
209
|
+
`Please provide a valid JSON object with structure: { "values": [{ "email": "..." }, ...] }. ` +
|
|
210
|
+
`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
// Already parsed by n8n's JSON field type
|
|
215
|
+
parsedValue = cellValue;
|
|
216
|
+
}
|
|
217
|
+
// Validate that it's an object with values array
|
|
218
|
+
if (typeof parsedValue !== 'object' || parsedValue === null) {
|
|
219
|
+
throw new Error(`Invalid objectValue for MULTI_CONTACT_LIST column (Column ID: ${colIdNum}). ` +
|
|
220
|
+
`Expected a JSON object with "values" array, got ${typeof parsedValue}.`);
|
|
221
|
+
}
|
|
222
|
+
// Validate that it has a values array
|
|
223
|
+
if (!Array.isArray(parsedValue.values)) {
|
|
224
|
+
throw new Error(`Invalid objectValue for MULTI_CONTACT_LIST column (Column ID: ${colIdNum}). ` +
|
|
225
|
+
`Expected a JSON object with "values" array property. Example: { "values": [{ "email": "user@example.com" }] }`);
|
|
226
|
+
}
|
|
227
|
+
// Validate that each value in the array has an email property
|
|
228
|
+
// Transform values to include objectType: "CONTACT" for each contact
|
|
229
|
+
const contactValues = parsedValue.values.map((value, i) => {
|
|
230
|
+
if (typeof value !== 'object' || value === null || !value.email) {
|
|
231
|
+
throw new Error(`Invalid objectValue for MULTI_CONTACT_LIST column (Column ID: ${colIdNum}). ` +
|
|
232
|
+
`Each item in the "values" array must be an object with an "email" property. ` +
|
|
233
|
+
`Example: { "values": [{ "email": "user@example.com" }] }`);
|
|
234
|
+
}
|
|
235
|
+
// Ensure each contact has objectType: "CONTACT"
|
|
236
|
+
return {
|
|
237
|
+
objectType: 'CONTACT',
|
|
238
|
+
email: value.email,
|
|
239
|
+
};
|
|
240
|
+
});
|
|
241
|
+
// For MULTI_CONTACT_LIST, objectValue should have structure:
|
|
242
|
+
// { "objectType": "MULTI_CONTACT", "values": [{ "objectType": "CONTACT", "email": "..." }, ...] }
|
|
243
|
+
// User provides the values array with emails, we add the objectType fields
|
|
244
|
+
// Don't include "strict" for MULTI_CONTACT_LIST as it causes parsing errors
|
|
245
|
+
// Ensure columnId is a number (not string) for the API
|
|
246
|
+
return {
|
|
247
|
+
columnId: Number(colIdNum),
|
|
248
|
+
objectValue: {
|
|
249
|
+
objectType: 'MULTI_CONTACT',
|
|
250
|
+
values: contactValues,
|
|
251
|
+
},
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
else if (columnType === 'MULTI_PICKLIST') {
|
|
255
|
+
// Parse the value - if it's a string, try to parse as JSON; if already an object, use it directly
|
|
256
|
+
// Expected format: { "values": ["Option 1", "Option 2", ...] }
|
|
257
|
+
let parsedValue;
|
|
258
|
+
if (typeof cellValue === 'string') {
|
|
259
|
+
try {
|
|
260
|
+
parsedValue = JSON.parse(cellValue);
|
|
261
|
+
}
|
|
262
|
+
catch (error) {
|
|
263
|
+
throw new Error(`Invalid JSON for MULTI_PICKLIST column (Column ID: ${colIdNum}). ` +
|
|
264
|
+
`Please provide a valid JSON object with structure: { "values": ["Option 1", "Option 2"] }. ` +
|
|
265
|
+
`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
// Already parsed by n8n's JSON field type
|
|
270
|
+
parsedValue = cellValue;
|
|
271
|
+
}
|
|
272
|
+
// Validate that it's an object with values array
|
|
273
|
+
if (typeof parsedValue !== 'object' || parsedValue === null) {
|
|
274
|
+
throw new Error(`Invalid objectValue for MULTI_PICKLIST column (Column ID: ${colIdNum}). ` +
|
|
275
|
+
`Expected a JSON object with "values" array, got ${typeof parsedValue}.`);
|
|
276
|
+
}
|
|
277
|
+
// Validate that it has a values array
|
|
278
|
+
if (!Array.isArray(parsedValue.values)) {
|
|
279
|
+
throw new Error(`Invalid objectValue for MULTI_PICKLIST column (Column ID: ${colIdNum}). ` +
|
|
280
|
+
`Expected a JSON object with "values" array property. Example: { "values": ["Option 1", "Option 2"] }`);
|
|
281
|
+
}
|
|
282
|
+
// For MULTI_PICKLIST, values should be an array of strings, not objects
|
|
283
|
+
// Transform values to ensure they're all strings
|
|
284
|
+
// Note: Picklist values must match exactly (case-sensitive) the options defined in the column
|
|
285
|
+
const picklistValues = parsedValue.values.map((value) => {
|
|
286
|
+
// Value should be a string (the option text)
|
|
287
|
+
if (typeof value === 'string') {
|
|
288
|
+
return value;
|
|
289
|
+
}
|
|
290
|
+
else if (typeof value === 'object' && value !== null && value.value) {
|
|
291
|
+
// If it's an object with a value property, extract the string value
|
|
292
|
+
return String(value.value);
|
|
195
293
|
}
|
|
196
294
|
else {
|
|
197
|
-
|
|
295
|
+
throw new Error(`Invalid value in MULTI_PICKLIST values array (Column ID: ${colIdNum}). ` +
|
|
296
|
+
`Each value must be a string (option text). ` +
|
|
297
|
+
`Note: Option values must match exactly (case-sensitive) the options defined in the MULTI_PICKLIST column.`);
|
|
198
298
|
}
|
|
299
|
+
});
|
|
300
|
+
// For MULTI_PICKLIST, objectValue should have structure:
|
|
301
|
+
// { "objectType": "MULTI_PICKLIST", "values": ["Option 1", "Option 2", ...] }
|
|
302
|
+
// User provides the values array with option strings, we use them directly (not wrapped in objects)
|
|
303
|
+
// Don't include "strict" for MULTI_PICKLIST as it may cause parsing errors
|
|
304
|
+
// Ensure columnId is a number (not string) for the API
|
|
305
|
+
return {
|
|
306
|
+
columnId: Number(colIdNum),
|
|
307
|
+
objectValue: {
|
|
308
|
+
objectType: 'MULTI_PICKLIST',
|
|
309
|
+
values: picklistValues,
|
|
310
|
+
},
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
// For CHECKBOX columns, convert string "true"/"false" to boolean
|
|
314
|
+
if (columnType === 'CHECKBOX') {
|
|
315
|
+
let boolValue;
|
|
316
|
+
if (typeof cellValue === 'boolean') {
|
|
317
|
+
boolValue = cellValue;
|
|
199
318
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
319
|
+
else if (typeof cellValue === 'string') {
|
|
320
|
+
const lowerValue = cellValue.toLowerCase().trim();
|
|
321
|
+
if (lowerValue === 'true' || lowerValue === '1' || lowerValue === 'yes') {
|
|
322
|
+
boolValue = true;
|
|
323
|
+
}
|
|
324
|
+
else if (lowerValue === 'false' || lowerValue === '0' || lowerValue === 'no' || lowerValue === '') {
|
|
325
|
+
boolValue = false;
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
// If it's not a recognized boolean string, try to parse it
|
|
329
|
+
throw new Error(`Invalid value for CHECKBOX column (Column ID: ${colIdNum}). ` +
|
|
330
|
+
`Expected boolean or string "true"/"false", got: ${cellValue}`);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
else if (cellValue === null || cellValue === undefined || cellValue === '') {
|
|
334
|
+
boolValue = false;
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
// Try to convert to boolean
|
|
338
|
+
boolValue = Boolean(cellValue);
|
|
339
|
+
}
|
|
340
|
+
return {
|
|
341
|
+
columnId: Number(colIdNum),
|
|
342
|
+
value: boolValue,
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
// For CHECKBOX columns, convert string "true"/"false" to boolean
|
|
346
|
+
if (columnType === 'CHECKBOX') {
|
|
347
|
+
let boolValue;
|
|
348
|
+
if (typeof cellValue === 'boolean') {
|
|
349
|
+
boolValue = cellValue;
|
|
350
|
+
}
|
|
351
|
+
else if (typeof cellValue === 'string') {
|
|
352
|
+
const lowerValue = cellValue.toLowerCase().trim();
|
|
353
|
+
if (lowerValue === 'true' || lowerValue === '1' || lowerValue === 'yes') {
|
|
354
|
+
boolValue = true;
|
|
355
|
+
}
|
|
356
|
+
else if (lowerValue === 'false' || lowerValue === '0' || lowerValue === 'no' || lowerValue === '') {
|
|
357
|
+
boolValue = false;
|
|
358
|
+
}
|
|
359
|
+
else {
|
|
360
|
+
// If it's not a recognized boolean string, try to parse it
|
|
361
|
+
throw new Error(`Invalid value for CHECKBOX column (Column ID: ${colIdNum}). ` +
|
|
362
|
+
`Expected boolean or string "true"/"false", got: ${cellValue}`);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
else if (cellValue === null || cellValue === undefined || cellValue === '') {
|
|
366
|
+
boolValue = false;
|
|
203
367
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
`Expected a JSON object, got ${typeof objectValue}.`);
|
|
368
|
+
else {
|
|
369
|
+
// Try to convert to boolean
|
|
370
|
+
boolValue = Boolean(cellValue);
|
|
208
371
|
}
|
|
209
|
-
// Use the parsed JSON directly as objectValue
|
|
210
372
|
return {
|
|
211
|
-
columnId: colIdNum,
|
|
212
|
-
|
|
213
|
-
strict: false,
|
|
373
|
+
columnId: Number(colIdNum),
|
|
374
|
+
value: boolValue,
|
|
214
375
|
};
|
|
215
376
|
}
|
|
216
377
|
// For regular columns, use value (use cleaned cellValue)
|
|
378
|
+
// Ensure columnId is a number (not string) for the API
|
|
217
379
|
return {
|
|
218
|
-
columnId: colIdNum,
|
|
380
|
+
columnId: Number(colIdNum),
|
|
219
381
|
value: cellValue,
|
|
220
382
|
};
|
|
221
383
|
});
|
|
@@ -471,7 +633,14 @@ async function executeRowOperation(operation, itemIndex) {
|
|
|
471
633
|
catch (error) {
|
|
472
634
|
// If we can't get columns, continue without column type info
|
|
473
635
|
}
|
|
474
|
-
|
|
636
|
+
// Filter out any cells with empty columnId or invalid data
|
|
637
|
+
const validCells = (cellsData.cell || []).filter((cell) => {
|
|
638
|
+
const columnId = cell.columnInputMethod === 'id'
|
|
639
|
+
? cell.columnIdManual
|
|
640
|
+
: cell.columnId;
|
|
641
|
+
return columnId && columnId !== '' && cell.value !== undefined;
|
|
642
|
+
});
|
|
643
|
+
const cells = validCells.map((cell) => {
|
|
475
644
|
let columnId;
|
|
476
645
|
if (cell.columnInputMethod === 'id') {
|
|
477
646
|
columnId = cell.columnIdManual || '';
|
|
@@ -479,7 +648,11 @@ async function executeRowOperation(operation, itemIndex) {
|
|
|
479
648
|
else {
|
|
480
649
|
columnId = cell.columnId || '';
|
|
481
650
|
}
|
|
651
|
+
// Parse columnId - keep as number for API, but ensure it's valid
|
|
482
652
|
const colIdNum = parseInt(columnId, 10);
|
|
653
|
+
if (isNaN(colIdNum)) {
|
|
654
|
+
throw new Error(`Invalid column ID: ${columnId}`);
|
|
655
|
+
}
|
|
483
656
|
const column = columnsMap.get(colIdNum);
|
|
484
657
|
const columnType = column?.type;
|
|
485
658
|
// Clean up the value - remove surrounding quotes if present
|
|
@@ -493,37 +666,188 @@ async function executeRowOperation(operation, itemIndex) {
|
|
|
493
666
|
}
|
|
494
667
|
}
|
|
495
668
|
// Handle MULTI_CONTACT_LIST and MULTI_PICKLIST columns with objectValue
|
|
496
|
-
// User
|
|
497
|
-
if (columnType === 'MULTI_CONTACT_LIST'
|
|
498
|
-
// Parse the value as JSON
|
|
499
|
-
let
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
669
|
+
// User provides a JSON object (field type is 'json' so n8n parses it automatically)
|
|
670
|
+
if (columnType === 'MULTI_CONTACT_LIST') {
|
|
671
|
+
// Parse the value - if it's a string, try to parse as JSON; if already an object, use it directly
|
|
672
|
+
let parsedValue;
|
|
673
|
+
if (typeof cellValue === 'string') {
|
|
674
|
+
try {
|
|
675
|
+
parsedValue = JSON.parse(cellValue);
|
|
676
|
+
}
|
|
677
|
+
catch (error) {
|
|
678
|
+
throw new Error(`Invalid JSON for MULTI_CONTACT_LIST column (Column ID: ${colIdNum}). ` +
|
|
679
|
+
`Please provide a valid JSON object with structure: { "values": [{ "email": "..." }, ...] }. ` +
|
|
680
|
+
`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
else {
|
|
684
|
+
// Already parsed by n8n's JSON field type
|
|
685
|
+
parsedValue = cellValue;
|
|
686
|
+
}
|
|
687
|
+
// Validate that it's an object with values array
|
|
688
|
+
if (typeof parsedValue !== 'object' || parsedValue === null) {
|
|
689
|
+
throw new Error(`Invalid objectValue for MULTI_CONTACT_LIST column (Column ID: ${colIdNum}). ` +
|
|
690
|
+
`Expected a JSON object with "values" array, got ${typeof parsedValue}.`);
|
|
691
|
+
}
|
|
692
|
+
// Validate that it has a values array
|
|
693
|
+
if (!Array.isArray(parsedValue.values)) {
|
|
694
|
+
throw new Error(`Invalid objectValue for MULTI_CONTACT_LIST column (Column ID: ${colIdNum}). ` +
|
|
695
|
+
`Expected a JSON object with "values" array property. Example: { "values": [{ "email": "user@example.com" }] }`);
|
|
696
|
+
}
|
|
697
|
+
// Validate that each value in the array has an email property
|
|
698
|
+
// Transform values to include objectType: "CONTACT" for each contact
|
|
699
|
+
const contactValues = parsedValue.values.map((value, i) => {
|
|
700
|
+
if (typeof value !== 'object' || value === null || !value.email) {
|
|
701
|
+
throw new Error(`Invalid objectValue for MULTI_CONTACT_LIST column (Column ID: ${colIdNum}). ` +
|
|
702
|
+
`Each item in the "values" array must be an object with an "email" property. ` +
|
|
703
|
+
`Example: { "values": [{ "email": "user@example.com" }] }`);
|
|
704
|
+
}
|
|
705
|
+
// Ensure each contact has objectType: "CONTACT"
|
|
706
|
+
return {
|
|
707
|
+
objectType: 'CONTACT',
|
|
708
|
+
email: value.email,
|
|
709
|
+
};
|
|
710
|
+
});
|
|
711
|
+
// For MULTI_CONTACT_LIST, objectValue should have structure:
|
|
712
|
+
// { "objectType": "MULTI_CONTACT", "values": [{ "objectType": "CONTACT", "email": "..." }, ...] }
|
|
713
|
+
// User provides the values array with emails, we add the objectType fields
|
|
714
|
+
// Don't include "strict" for MULTI_CONTACT_LIST as it causes parsing errors
|
|
715
|
+
// Ensure columnId is a number (not string) for the API
|
|
716
|
+
return {
|
|
717
|
+
columnId: Number(colIdNum),
|
|
718
|
+
objectValue: {
|
|
719
|
+
objectType: 'MULTI_CONTACT',
|
|
720
|
+
values: contactValues,
|
|
721
|
+
},
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
else if (columnType === 'MULTI_PICKLIST') {
|
|
725
|
+
// Parse the value - if it's a string, try to parse as JSON; if already an object, use it directly
|
|
726
|
+
// Expected format: { "values": ["Option 1", "Option 2", ...] }
|
|
727
|
+
let parsedValue;
|
|
728
|
+
if (typeof cellValue === 'string') {
|
|
729
|
+
try {
|
|
730
|
+
parsedValue = JSON.parse(cellValue);
|
|
731
|
+
}
|
|
732
|
+
catch (error) {
|
|
733
|
+
throw new Error(`Invalid JSON for MULTI_PICKLIST column (Column ID: ${colIdNum}). ` +
|
|
734
|
+
`Please provide a valid JSON object with structure: { "values": ["Option 1", "Option 2"] }. ` +
|
|
735
|
+
`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
else {
|
|
739
|
+
// Already parsed by n8n's JSON field type
|
|
740
|
+
parsedValue = cellValue;
|
|
741
|
+
}
|
|
742
|
+
// Validate that it's an object with values array
|
|
743
|
+
if (typeof parsedValue !== 'object' || parsedValue === null) {
|
|
744
|
+
throw new Error(`Invalid objectValue for MULTI_PICKLIST column (Column ID: ${colIdNum}). ` +
|
|
745
|
+
`Expected a JSON object with "values" array, got ${typeof parsedValue}.`);
|
|
746
|
+
}
|
|
747
|
+
// Validate that it has a values array
|
|
748
|
+
if (!Array.isArray(parsedValue.values)) {
|
|
749
|
+
throw new Error(`Invalid objectValue for MULTI_PICKLIST column (Column ID: ${colIdNum}). ` +
|
|
750
|
+
`Expected a JSON object with "values" array property. Example: { "values": ["Option 1", "Option 2"] }`);
|
|
751
|
+
}
|
|
752
|
+
// For MULTI_PICKLIST, values should be an array of strings, not objects
|
|
753
|
+
// Transform values to ensure they're all strings
|
|
754
|
+
// Note: Picklist values must match exactly (case-sensitive) the options defined in the column
|
|
755
|
+
const picklistValues = parsedValue.values.map((value) => {
|
|
756
|
+
// Value should be a string (the option text)
|
|
757
|
+
if (typeof value === 'string') {
|
|
758
|
+
return value;
|
|
759
|
+
}
|
|
760
|
+
else if (typeof value === 'object' && value !== null && value.value) {
|
|
761
|
+
// If it's an object with a value property, extract the string value
|
|
762
|
+
return String(value.value);
|
|
503
763
|
}
|
|
504
764
|
else {
|
|
505
|
-
|
|
765
|
+
throw new Error(`Invalid value in MULTI_PICKLIST values array (Column ID: ${colIdNum}). ` +
|
|
766
|
+
`Each value must be a string (option text). ` +
|
|
767
|
+
`Note: Option values must match exactly (case-sensitive) the options defined in the MULTI_PICKLIST column.`);
|
|
506
768
|
}
|
|
769
|
+
});
|
|
770
|
+
// For MULTI_PICKLIST, objectValue should have structure:
|
|
771
|
+
// { "objectType": "MULTI_PICKLIST", "values": ["Option 1", "Option 2", ...] }
|
|
772
|
+
// User provides the values array with option strings, we use them directly (not wrapped in objects)
|
|
773
|
+
// Don't include "strict" for MULTI_PICKLIST as it may cause parsing errors
|
|
774
|
+
// Ensure columnId is a number (not string) for the API
|
|
775
|
+
return {
|
|
776
|
+
columnId: Number(colIdNum),
|
|
777
|
+
objectValue: {
|
|
778
|
+
objectType: 'MULTI_PICKLIST',
|
|
779
|
+
values: picklistValues,
|
|
780
|
+
},
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
// For CHECKBOX columns, convert string "true"/"false" to boolean
|
|
784
|
+
if (columnType === 'CHECKBOX') {
|
|
785
|
+
let boolValue;
|
|
786
|
+
if (typeof cellValue === 'boolean') {
|
|
787
|
+
boolValue = cellValue;
|
|
507
788
|
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
789
|
+
else if (typeof cellValue === 'string') {
|
|
790
|
+
const lowerValue = cellValue.toLowerCase().trim();
|
|
791
|
+
if (lowerValue === 'true' || lowerValue === '1' || lowerValue === 'yes') {
|
|
792
|
+
boolValue = true;
|
|
793
|
+
}
|
|
794
|
+
else if (lowerValue === 'false' || lowerValue === '0' || lowerValue === 'no' || lowerValue === '') {
|
|
795
|
+
boolValue = false;
|
|
796
|
+
}
|
|
797
|
+
else {
|
|
798
|
+
// If it's not a recognized boolean string, try to parse it
|
|
799
|
+
throw new Error(`Invalid value for CHECKBOX column (Column ID: ${colIdNum}). ` +
|
|
800
|
+
`Expected boolean or string "true"/"false", got: ${cellValue}`);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
else if (cellValue === null || cellValue === undefined || cellValue === '') {
|
|
804
|
+
boolValue = false;
|
|
805
|
+
}
|
|
806
|
+
else {
|
|
807
|
+
// Try to convert to boolean
|
|
808
|
+
boolValue = Boolean(cellValue);
|
|
809
|
+
}
|
|
810
|
+
return {
|
|
811
|
+
columnId: Number(colIdNum),
|
|
812
|
+
value: boolValue,
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
// For CHECKBOX columns, convert string "true"/"false" to boolean
|
|
816
|
+
if (columnType === 'CHECKBOX') {
|
|
817
|
+
let boolValue;
|
|
818
|
+
if (typeof cellValue === 'boolean') {
|
|
819
|
+
boolValue = cellValue;
|
|
820
|
+
}
|
|
821
|
+
else if (typeof cellValue === 'string') {
|
|
822
|
+
const lowerValue = cellValue.toLowerCase().trim();
|
|
823
|
+
if (lowerValue === 'true' || lowerValue === '1' || lowerValue === 'yes') {
|
|
824
|
+
boolValue = true;
|
|
825
|
+
}
|
|
826
|
+
else if (lowerValue === 'false' || lowerValue === '0' || lowerValue === 'no' || lowerValue === '') {
|
|
827
|
+
boolValue = false;
|
|
828
|
+
}
|
|
829
|
+
else {
|
|
830
|
+
// If it's not a recognized boolean string, try to parse it
|
|
831
|
+
throw new Error(`Invalid value for CHECKBOX column (Column ID: ${colIdNum}). ` +
|
|
832
|
+
`Expected boolean or string "true"/"false", got: ${cellValue}`);
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
else if (cellValue === null || cellValue === undefined || cellValue === '') {
|
|
836
|
+
boolValue = false;
|
|
511
837
|
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
`Expected a JSON object, got ${typeof objectValue}.`);
|
|
838
|
+
else {
|
|
839
|
+
// Try to convert to boolean
|
|
840
|
+
boolValue = Boolean(cellValue);
|
|
516
841
|
}
|
|
517
|
-
// Use the parsed JSON directly as objectValue
|
|
518
842
|
return {
|
|
519
|
-
columnId: colIdNum,
|
|
520
|
-
|
|
521
|
-
strict: false,
|
|
843
|
+
columnId: Number(colIdNum),
|
|
844
|
+
value: boolValue,
|
|
522
845
|
};
|
|
523
846
|
}
|
|
524
847
|
// For regular columns, use value (use cleaned cellValue)
|
|
848
|
+
// Ensure columnId is a number (not string) for the API
|
|
525
849
|
return {
|
|
526
|
-
columnId: colIdNum,
|
|
850
|
+
columnId: Number(colIdNum),
|
|
527
851
|
value: cellValue,
|
|
528
852
|
};
|
|
529
853
|
});
|