You are encountering the following error in SuiteScript 2.x:
TypeError: Cannot find function endsWith in object ...
This error occurs when you’re attempting to append data to a CSV file using file.getContents() and then trying to check if it ends with a newline (n) using .endsWith(). In SuiteScript 2.x, this function may not be available for the object returned by getContents(). Additionally, if the file doesn’t end with a newline, appending a new row could cause the new row to be added as a column instead of a new line.
Root Cause:
- The file.getContents()method returns the entire content of the file, which is expected to be a string.
- If the file is malformed, or if the last row in the file doesn’t end with a newline, the new data might be appended incorrectly (as part of the last row instead of a new row).
- The error arises from trying to use endsWith()on an object that doesn’t support this method, likely becausegetContents()is returning something other than a string (or the string is malformed).
Solution:
To handle this issue and ensure that rows are appended correctly to the CSV file, follow these steps:
- Load the File:
-  Use file.load()to load the file from the file cabinet.
- Ensure String Content:
-  Convert the result from getContents()into a string. This ensures that subsequent operations treat the file content as a valid string.
- Check for Newline at End of File:
-  Use slice(-1)to check whether the content ends with a newline (n). This is a simple and safe method supported in SuiteScript 2.x.
- Append New Row Safely:
- If the content doesn’t end with a newline, prepend a newline before appending the new row.
Implementation Example:
Here’s how you can fix this issue and safely append rows to a CSV file:
/**
 * Safely appends a new row to the given CSV file object.
 * 
 * @param {Object} fileObj - The file object representing the CSV file.
 * @param {Array} rowValues - An array of values for the new row.
 */
function appendCsvRowSafely(fileObj, rowValues) {
    // Ensure the file contents are a string
    var content = String(fileObj.getContents());
    
    // Check if the last character is a newline
    var endsWithNewline = content.slice(-1) === 'n';
    
    // Convert the row values to a comma-separated string
    var row = rowValues.join(',');
    
    // If the content doesn't end with a newline, add one before appending
    if (!endsWithNewline) {
        row = 'n' + row;
    }
    
    // Append the row and save the file
    fileObj.appendLine({ value: row });
    fileObj.save();
}
Usage Example:
Here’s how you can use this function in the context of your CSV handling logic:
// Load the existing file
var existingFile = file.load({ id: fileId });
// Prepare the data for the new row
var newRow = [
    'NewItem',
    'New Description',
    'Strand Count',
    'Class',
    'Component #1',
    'Qty'
];
// Append the new row safely
appendCsvRowSafely(existingFile, newRow);
This ensures that if the CSV file does not end with a newline, it will be correctly formatted by prepending one before appending the new row. This will prevent the new data from being appended as part of the last column.
Best Practices:
- Always verify that getContents()returns a valid string before performing string operations.
- Use slice(-1)instead of.endsWith()for better compatibility with SuiteScript 2.x.
- Ensure that each row in your CSV ends with a newline to maintain proper formatting when adding new data.
Additional Notes:
- This approach works seamlessly for CSV files, where each row is represented by a single line of comma-separated values.
- If you are appending multiple rows at once, ensure that you’re consistently applying the newline handling logic for each row.