Skip to content

feat: Implement CSV import/export functionality#5

Merged
abdullahmujahidali merged 3 commits into
mainfrom
feature/csv-io
Dec 15, 2025
Merged

feat: Implement CSV import/export functionality#5
abdullahmujahidali merged 3 commits into
mainfrom
feature/csv-io

Conversation

@abdullahmujahidali

@abdullahmujahidali abdullahmujahidali commented Dec 15, 2025

Copy link
Copy Markdown
Owner
  • Added CSV import/export capabilities with auto-detection of delimiters.
  • Introduced new API methods: csvToWorkbook, csvToSheet, sheetToCsv, and sheetsToCsv.
  • Created comprehensive tests for CSV import and export functionalities.
  • Documented CSV format options and implementation decisions in ADR-005.
  • Updated README to reflect new features and usage examples.

Summary by CodeRabbit

  • New Features

    • CSV import/export with automatic delimiter detection, quoted/multi-line field support, configurable options, and type inference on import.
  • Documentation

    • README updated with CSV usage examples and feature list.
    • New architecture decision record describing CSV format design and trade-offs.
  • Tests

    • Comprehensive test suite covering CSV export/import, delimiter detection, formatting options, edge cases, and roundtrip validation.
  • Chores

    • Public formats API exported and TypeScript DOM typings added.

✏️ Tip: You can customize this high-level summary in your review settings.

- Added CSV import/export capabilities with auto-detection of delimiters.
- Introduced new API methods: `csvToWorkbook`, `csvToSheet`, `sheetToCsv`, and `sheetsToCsv`.
- Created comprehensive tests for CSV import and export functionalities.
- Documented CSV format options and implementation decisions in ADR-005.
- Updated README to reflect new features and usage examples.
@coderabbitai

coderabbitai Bot commented Dec 15, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Adds RFC 4180–aware CSV import and export: new reader and writer modules with delimiter auto-detection, type inference, configurable options and defaults, new types and exports, documentation (ADR + README) and an extensive test suite.

Changes

Cohort / File(s) Summary
Documentation
README.md, docs/decisions/005-csv-format.md, docs/decisions/README.md
README adds CSV Import/Export section and examples; ADR-005 describes design, RFC 4180 choices, delimiter detection, type-detection, API surface, consequences and future work; ADR index updated.
CSV Types & Defaults
src/formats/csv.types.ts
Adds CsvExportOptions, CsvImportOptions, CsvImportResult interfaces and DEFAULT_CSV_EXPORT_OPTIONS, DEFAULT_CSV_IMPORT_OPTIONS constants with documented defaults.
CSV Writer (export)
src/formats/csv.writer.ts
Implements sheetToCsv, sheetToCsvBuffer, sheetsToCsv; handles value formatting (null, number, boolean, date, rich text), date formatting, RFC 4180 escaping, BOM and range handling.
CSV Reader (import)
src/formats/csv.reader.ts
Implements csvToWorkbook, csvToSheet, csvBufferToWorkbook; includes delimiter detection, RFC 4180-compliant parsing (quotes, escapes, multiline), type conversion (null, boolean, number, date), BOM handling, progress callbacks and warnings.
Public Exports
src/formats/index.ts, src/index.ts
Re-exports CSV types, defaults, reader and writer APIs from src/formats into the public surface.
Tests & Config
tests/csv.test.ts, tsconfig.json
Adds comprehensive CSV import/export tests (escape cases, delimiters, type detection, roundtrips, BOM, progress, error cases); tsconfig.json adds "DOM" to lib.

// Sequence Diagram(s) omitted (changes do not meet diagram criteria).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Areas to focus review on:
    • src/formats/csv.reader.ts: delimiter detection, RFC 4180 parsing (quotes, escaped quotes, multiline) and progress/cancellation points.
    • Type conversion utilities: parseNumber, parseDate, convertValue edge cases (NaN, Infinity, ambiguous dates, percentages, currencies).
    • src/formats/csv.writer.ts: escaping logic (escapeField) and date formatting correctness across formats.
    • Tests in tests/csv.test.ts: ensure coverage matches parser/writer semantics and edge cases (BOM, Windows CRLF, maxRows).
    • Public API and defaults in src/formats/csv.types.ts: ensure option names and defaults align with implementation.

Poem

🐰 I nibble commas, leap through quoted rows,
Detecting delimiters where the wild data grows.
Fields snug in quotes, newlines curl and play—
From sheet to string, then back the bunny-way. ✨
A tiny hop for code, a joyful CSV day!

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Description check ❓ Inconclusive The PR description covers key aspects of the changes but lacks several required template sections including Type of Change selection, Related Issues reference, Checklist completion, Testing details, and ADR acknowledgment. Complete the template by adding Type of Change (check 'New feature'), Related Issues if applicable, checking off Checklist items, providing Testing section details, and confirming ADR-005 was added.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the main change: implementing CSV import/export functionality, which is the core objective of the pull request.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/csv-io

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 49e918d and 01bcc6d.

📒 Files selected for processing (4)
  • docs/decisions/005-csv-format.md (1 hunks)
  • src/formats/csv.reader.ts (1 hunks)
  • src/formats/csv.types.ts (1 hunks)
  • tests/csv.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/formats/csv.types.ts
🧰 Additional context used
🧬 Code graph analysis (1)
tests/csv.test.ts (2)
src/formats/csv.writer.ts (3)
  • sheetToCsv (32-65)
  • sheetToCsvBuffer (74-77)
  • sheetsToCsv (86-97)
src/formats/csv.reader.ts (3)
  • csvToWorkbook (30-37)
  • csvToSheet (47-113)
  • csvBufferToWorkbook (122-127)
🔇 Additional comments (13)
docs/decisions/005-csv-format.md (1)

1-96: LGTM! Excellent ADR documentation.

The ADR is comprehensive and well-structured, covering RFC 4180 compliance, auto-detection strategies, type detection patterns, API design, and balanced consequences. The date has been correctly updated to 2025-12-15, resolving the previous review concern.

tests/csv.test.ts (4)

12-224: LGTM! Comprehensive export tests.

The CSV export test suite thoroughly covers the core functionality and edge cases including RFC 4180 compliance (escaping, quoting), custom delimiters, BOM handling, type formatting, and range exports.


226-547: LGTM! Thorough import tests.

The CSV import test suite is comprehensive, covering RFC 4180 parsing, delimiter auto-detection, type inference, date format handling, and numerous edge cases. The test at lines 537-546 specifically validates escaped quote handling during delimiter detection.


549-613: LGTM! Complete API coverage.

Tests for csvToSheet and csvBufferToWorkbook cover the remaining public API surface, including custom start positions, import statistics, headers extraction, and BOM handling.


615-653: LGTM! Roundtrip validation.

The roundtrip tests effectively validate data integrity across export/import cycles, ensuring proper handling of special characters and data preservation.

src/formats/csv.reader.ts (8)

12-37: LGTM! Clean workbook creation.

The function is well-documented and correctly delegates CSV parsing to csvToSheet after creating the workbook and sheet structure.


39-113: LGTM! Well-structured import logic.

The csvToSheet function is well-organized with clear separation of concerns: option merging, delimiter detection, CSV parsing, header extraction, type conversion, and progress reporting. The implementation correctly handles all the configurable options.


115-127: LGTM! Proper buffer handling.

The function correctly decodes the UTF-8 buffer and strips the BOM if present before delegating to csvToWorkbook.


129-165: LGTM! Escaped quote handling fixed.

The delimiter detection now correctly handles escaped quotes (doubled quotes) using index-based iteration with lookahead. Lines 148-150 properly skip both quotes of an escaped pair without toggling the inQuotes state, addressing the previous review concern.


167-264: LGTM! Robust RFC 4180 parser.

The CSV parser is well-implemented with proper handling of quoted fields, escaped quotes, multi-line fields, and edge cases. The line ending normalization and state machine approach ensure correct parsing of complex CSV files.


266-300: LGTM! Logical type conversion.

The type conversion function follows a sensible priority order (empty → boolean → number → date → string) and respects the configuration options for number and date detection.


302-342: LGTM! Comprehensive number parsing.

The number parsing handles percentages, currency symbols, and thousands separators while avoiding false positives. The regex at line 310 cleverly excludes all letters except 'e/E' for scientific notation, and the final validation at line 337 ensures only valid number formats are accepted.


344-409: LGTM! Date parsing with proper validation.

The date parsing logic correctly handles ISO dates and custom formats. The validation at line 400 now properly rejects invalid year and day values (year > 0 && day > 0), addressing the previous review concern. The subsequent validation at line 403 ensures the Date constructor produced a valid date matching the input components, which catches out-of-range months and days.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov-commenter

codecov-commenter commented Dec 15, 2025

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 98.80000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.45%. Comparing base (48ab171) to head (01bcc6d).

Files with missing lines Patch % Lines
src/formats/csv.reader.ts 98.87% 2 Missing ⚠️
src/formats/csv.writer.ts 98.59% 1 Missing ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
Additional details and impacted files
@@            Coverage Diff             @@
##             main       #5      +/-   ##
==========================================
+ Coverage   84.71%   88.45%   +3.73%     
==========================================
  Files           7       10       +3     
  Lines         772     1022     +250     
  Branches      180      260      +80     
==========================================
+ Hits          654      904     +250     
  Misses        118      118              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (3)
tests/csv.test.ts (1)

163-309: Consider adding date detection tests.

The test suite comprehensively covers most import functionality, but there's no test for date/datetime detection mentioned in the ADR (lines 43-44 in 005-csv-format.md). Consider adding tests for the detectDates option with ISO date patterns.

it('should detect dates when enabled', () => {
  const csv = '2024-01-15,2024-12-31T23:59:59';
  const workbook = csvToWorkbook(csv, { detectDates: true });
  const sheet = workbook.getSheetByIndex(0)!;
  
  expect(sheet.cell('A1').value).toBeInstanceOf(Date);
  expect(sheet.cell('B1').value).toBeInstanceOf(Date);
});

it('should not detect dates when disabled', () => {
  const csv = '2024-01-15';
  const workbook = csvToWorkbook(csv, { detectDates: false });
  const sheet = workbook.getSheetByIndex(0)!;
  
  expect(typeof sheet.cell('A1').value).toBe('string');
});
src/formats/csv.reader.ts (1)

299-336: Consider handling European number formats more explicitly.

The comment on line 320 mentions handling different decimal formats, but the implementation only removes commas as thousands separators. European number formats using periods for thousands (e.g., 1.000.000) won't be correctly parsed.

Since the validation regex on line 331 requires a standard format, these European numbers will correctly remain as strings. However, consider either:

  1. Explicitly documenting that only Anglo-Saxon number formats (comma thousands, period decimal) are supported
  2. Or implementing heuristic detection for European formats (period thousands, comma decimal)
src/formats/csv.writer.ts (1)

86-97: Potential ambiguity when multiple sheets share the same name

sheetsToCsv uses sheet.name as the Map key, so later sheets with the same name silently overwrite earlier ones.

If duplicate names are possible in your model, consider either:

  • Throwing or warning on duplicates, or
  • Accepting a custom key function / suffix strategy.

If sheet names are guaranteed unique, a brief comment to that effect would clarify the intent.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 48ab171 and 49e918d.

📒 Files selected for processing (10)
  • README.md (1 hunks)
  • docs/decisions/005-csv-format.md (1 hunks)
  • docs/decisions/README.md (1 hunks)
  • src/formats/csv.reader.ts (1 hunks)
  • src/formats/csv.types.ts (1 hunks)
  • src/formats/csv.writer.ts (1 hunks)
  • src/formats/index.ts (1 hunks)
  • src/index.ts (1 hunks)
  • tests/csv.test.ts (1 hunks)
  • tsconfig.json (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
src/formats/csv.types.ts (1)
src/formats/index.ts (5)
  • CsvExportOptions (3-3)
  • CsvImportOptions (4-4)
  • CsvImportResult (5-5)
  • DEFAULT_CSV_EXPORT_OPTIONS (9-9)
  • DEFAULT_CSV_IMPORT_OPTIONS (10-10)
src/formats/csv.reader.ts (2)
src/formats/csv.types.ts (3)
  • CsvImportOptions (73-149)
  • DEFAULT_CSV_IMPORT_OPTIONS (194-208)
  • CsvImportResult (154-174)
src/core/Sheet.ts (1)
  • rows (549-551)
tests/csv.test.ts (2)
src/formats/csv.writer.ts (3)
  • sheetToCsv (32-65)
  • sheetToCsvBuffer (74-77)
  • sheetsToCsv (86-97)
src/formats/csv.reader.ts (3)
  • csvToWorkbook (30-37)
  • csvToSheet (47-113)
  • csvBufferToWorkbook (122-127)
src/formats/csv.writer.ts (1)
src/formats/csv.types.ts (2)
  • CsvExportOptions (8-68)
  • DEFAULT_CSV_EXPORT_OPTIONS (179-189)
🔇 Additional comments (17)
docs/decisions/README.md (1)

17-17: LGTM!

The ADR index entry is properly formatted and consistent with existing entries.

docs/decisions/005-csv-format.md (2)

6-71: LGTM!

The technical decisions are well-documented with clear rationale. The RFC 4180 compliance, auto-detection strategy, and API design align with the implementation.


73-96: LGTM!

Good documentation of both benefits and limitations. The acknowledgment of CSV's lossy nature and missing streaming support sets appropriate expectations.

src/index.ts (1)

46-47: LGTM!

The public API export is clean and follows the existing pattern. The comment appropriately indicates future Excel format support.

README.md (2)

78-78: LGTM!

The feature list addition accurately reflects the new CSV import/export capability.


86-114: LGTM!

The CSV documentation is clear and comprehensive. The code examples demonstrate both import and export workflows correctly, and the feature list accurately describes the implementation capabilities.

tests/csv.test.ts (3)

12-134: LGTM!

Excellent test coverage for CSV export functionality. The tests cover empty sheets, various data types, RFC 4180 escaping rules, custom options, and range exports.


136-161: LGTM!

The tests for buffer export and multi-sheet export provide appropriate coverage for these wrapper functions.


311-416: LGTM!

Excellent test coverage for import functions and roundtrip integrity. The tests verify that data survives the export/import cycle, including special characters that require escaping.

src/formats/csv.types.ts (2)

73-174: LGTM!

The import options and result types are comprehensive and well-documented. The option names are clear, and the default values are sensible.


179-189: Verify the includeHeaders default value.

The default export options include includeHeaders: true, but this option doesn't appear to be implemented in the export logic (as flagged in the previous comment about lines 33-37). Verify whether this default should be removed or if the feature needs to be implemented.

src/formats/csv.reader.ts (4)

30-127: LGTM!

The public API functions are well-structured. The delegation pattern keeps the code DRY, and the buffer handling correctly deals with UTF-8 decoding and BOM removal.


170-258: LGTM!

The CSV parser correctly implements RFC 4180 with proper handling of quoted fields, escaped quotes (doubled), and multi-line values. The state machine approach is clear and handles edge cases correctly.


263-294: LGTM!

The type conversion logic is well-structured with appropriate fallbacks. The conditional detection based on options provides good user control.


341-403: The ADR does not imply datetime support. Line 43 specifies "ISO date | Date | 2024-01-15 → Date object"—a date-only format. The "Negative" section explicitly notes "Limited date format detection," and "Future Enhancements" mentions additional date patterns, not datetime support. The current implementation correctly aligns with the ADR's date-only scope.

Likely an incorrect or invalid review comment.

src/formats/index.ts (1)

1-17: CSV barrel exports look clean and consistent

Re-exports are well-organized (types vs values) and match the intended CSV API surface; this should integrate cleanly with the existing top-level index.

src/formats/csv.writer.ts (1)

99-204: Value formatting and escaping cover key edge cases

The helpers handle nulls, numbers (including NaN/Infinity), booleans, dates (ISO/locale/custom), and rich text, and escapeField correctly quotes fields per RFC 4180 (delimiter/quote/newline) with proper quote doubling and regex escaping. This is a solid foundation for CSV export.

Comment thread docs/decisions/005-csv-format.md Outdated
Comment thread src/formats/csv.reader.ts
Comment thread src/formats/csv.reader.ts
Comment thread src/formats/csv.types.ts Outdated
Comment thread src/formats/csv.writer.ts
Comment on lines +32 to +65
export function sheetToCsv(sheet: Sheet, options: CsvExportOptions = {}): string {
const opts = { ...DEFAULT_CSV_EXPORT_OPTIONS, ...options };
const { delimiter, rowDelimiter, quoteChar, quoteAllFields, includeBom } = opts;

// Determine range to export
const range = options.range
? parseRangeReference(options.range)
: sheet.dimensions;

if (!range) {
// Empty sheet
return includeBom ? UTF8_BOM : '';
}

const rows: string[] = [];

// Build CSV rows
for (let rowIdx = range.startRow; rowIdx <= range.endRow; rowIdx++) {
const rowValues: string[] = [];

for (let colIdx = range.startCol; colIdx <= range.endCol; colIdx++) {
const cell = sheet.getCell(rowIdx, colIdx);
const value = cell?.value ?? null;
const formatted = formatValue(value, opts);
const escaped = escapeField(formatted, delimiter, quoteChar, quoteAllFields);
rowValues.push(escaped);
}

rows.push(rowValues.join(delimiter));
}

const csv = rows.join(rowDelimiter);
return includeBom ? UTF8_BOM + csv : csv;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

includeHeaders option is currently ignored in export loop

CsvExportOptions defines includeHeaders, but sheetToCsv always exports every row in range, regardless of this flag. Callers setting includeHeaders: false will still get the first row, which is surprising given the option name and JSDoc.

Consider wiring the flag into the row iteration so the first row of the exported range is treated as the “header” row and skipped when includeHeaders is false, e.g.:

-export function sheetToCsv(sheet: Sheet, options: CsvExportOptions = {}): string {
-  const opts = { ...DEFAULT_CSV_EXPORT_OPTIONS, ...options };
-  const { delimiter, rowDelimiter, quoteChar, quoteAllFields, includeBom } = opts;
+export function sheetToCsv(sheet: Sheet, options: CsvExportOptions = {}): string {
+  const opts = { ...DEFAULT_CSV_EXPORT_OPTIONS, ...options };
+  const { delimiter, rowDelimiter, quoteChar, quoteAllFields, includeBom, includeHeaders } = opts;
@@
-  // Build CSV rows
-  for (let rowIdx = range.startRow; rowIdx <= range.endRow; rowIdx++) {
+  // Build CSV rows
+  const startRow = includeHeaders ? range.startRow : range.startRow + 1;
+  for (let rowIdx = startRow; rowIdx <= range.endRow; rowIdx++) {

(Behavior would be “first row of the exported range is considered the header”.)

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function sheetToCsv(sheet: Sheet, options: CsvExportOptions = {}): string {
const opts = { ...DEFAULT_CSV_EXPORT_OPTIONS, ...options };
const { delimiter, rowDelimiter, quoteChar, quoteAllFields, includeBom } = opts;
// Determine range to export
const range = options.range
? parseRangeReference(options.range)
: sheet.dimensions;
if (!range) {
// Empty sheet
return includeBom ? UTF8_BOM : '';
}
const rows: string[] = [];
// Build CSV rows
for (let rowIdx = range.startRow; rowIdx <= range.endRow; rowIdx++) {
const rowValues: string[] = [];
for (let colIdx = range.startCol; colIdx <= range.endCol; colIdx++) {
const cell = sheet.getCell(rowIdx, colIdx);
const value = cell?.value ?? null;
const formatted = formatValue(value, opts);
const escaped = escapeField(formatted, delimiter, quoteChar, quoteAllFields);
rowValues.push(escaped);
}
rows.push(rowValues.join(delimiter));
}
const csv = rows.join(rowDelimiter);
return includeBom ? UTF8_BOM + csv : csv;
}
export function sheetToCsv(sheet: Sheet, options: CsvExportOptions = {}): string {
const opts = { ...DEFAULT_CSV_EXPORT_OPTIONS, ...options };
const { delimiter, rowDelimiter, quoteChar, quoteAllFields, includeBom, includeHeaders } = opts;
// Determine range to export
const range = options.range
? parseRangeReference(options.range)
: sheet.dimensions;
if (!range) {
// Empty sheet
return includeBom ? UTF8_BOM : '';
}
const rows: string[] = [];
// Build CSV rows
const startRow = includeHeaders ? range.startRow : range.startRow + 1;
for (let rowIdx = startRow; rowIdx <= range.endRow; rowIdx++) {
const rowValues: string[] = [];
for (let colIdx = range.startCol; colIdx <= range.endCol; colIdx++) {
const cell = sheet.getCell(rowIdx, colIdx);
const value = cell?.value ?? null;
const formatted = formatValue(value, opts);
const escaped = escapeField(formatted, delimiter, quoteChar, quoteAllFields);
rowValues.push(escaped);
}
rows.push(rowValues.join(delimiter));
}
const csv = rows.join(rowDelimiter);
return includeBom ? UTF8_BOM + csv : csv;
}
🤖 Prompt for AI Agents
In src/formats/csv.writer.ts around lines 32 to 65, the
CsvExportOptions.includeHeaders flag is ignored — the function always exports
every row in the provided range. Use the resolved opts.includeHeaders value to
treat the first row of the exported range as a header and skip it when
includeHeaders is false (e.g. start the row loop at range.startRow + 1 or
conditionally continue when rowIdx === range.startRow && !opts.includeHeaders).
Ensure skipping the header still respects includeBom and handles the case where
skipping leaves no data (return BOM or empty string accordingly).

Comment thread src/formats/csv.writer.ts
Comment on lines +74 to +77
export function sheetToCsvBuffer(sheet: Sheet, options: CsvExportOptions = {}): Uint8Array {
const csv = sheetToCsv(sheet, options);
return new TextEncoder().encode(csv);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's look at the csv.writer.ts file to understand the implementation
find . -type f -name "csv.writer.ts" | head -5

Repository: abdullahmujahidali/Cellify

Length of output: 97


🏁 Script executed:

# Let's also search for CsvExportOptions definition
rg "CsvExportOptions" --type ts -A 5 | head -50

Repository: abdullahmujahidali/Cellify

Length of output: 2426


🏁 Script executed:

# Let's read the csv.types.ts file to see the full CsvExportOptions definition
cat -n src/formats/csv.types.ts

Repository: abdullahmujahidali/Cellify

Length of output: 5263


🏁 Script executed:

# Read csv.writer.ts to see the full sheetToCsv implementation
cat -n src/formats/csv.writer.ts | head -100

Repository: abdullahmujahidali/Cellify

Length of output: 3433


🏁 Script executed:

# Search for tests related to CSV encoding
rg "encoding" --type ts -i | grep -i "csv\|test" | head -20

Repository: abdullahmujahidali/Cellify

Length of output: 304


🏁 Script executed:

# Check if encoding is used anywhere else in the codebase
rg "encoding" --type ts -B 2 -A 2

Repository: abdullahmujahidali/Cellify

Length of output: 710


🏁 Script executed:

# Find test files related to CSV
find . -type f \( -name "*test*" -o -name "*spec*" \) -path "*csv*" | head -10

Repository: abdullahmujahidali/Cellify

Length of output: 89


🏁 Script executed:

# Search for test files more broadly
fd -e test.ts -e spec.ts -e test.js -e spec.js | grep -i csv

Repository: abdullahmujahidali/Cellify

Length of output: 87


🏁 Script executed:

# Read the CSV test file
cat -n tests/csv.test.ts

Repository: abdullahmujahidali/Cellify

Length of output: 15811


encoding option is not honored in sheetToCsvBuffer (always UTF‑8)

CsvExportOptions.encoding allows 'utf-8' | 'utf-16' | 'ascii', but sheetToCsvBuffer always uses TextEncoder, which only produces UTF‑8 and doesn't accept an encoding parameter. This silently ignores non‑UTF‑8 encodings and can mislead callers.

At minimum, consider enforcing UTF‑8 here (and/or tightening the type/docs), e.g.:

 export function sheetToCsvBuffer(sheet: Sheet, options: CsvExportOptions = {}): Uint8Array {
-  const csv = sheetToCsv(sheet, options);
-  return new TextEncoder().encode(csv);
+  const encoding = options.encoding ?? DEFAULT_CSV_EXPORT_OPTIONS.encoding;
+  if (encoding !== 'utf-8') {
+    throw new Error(
+      `sheetToCsvBuffer currently supports only 'utf-8' encoding (got '${encoding}').`
+    );
+  }
+
+  const csv = sheetToCsv(sheet, options);
+  return new TextEncoder().encode(csv);
 }

Alternatively, implement real non‑UTF‑8 encoding support (Node Buffer, iconv, etc.) or drop those encodings from the options type.

Committable suggestion skipped: line range outside the PR's diff.

Comment thread tsconfig.json
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2022"],
"lib": ["ES2022", "DOM"],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check usage of DOM-specific APIs beyond TextEncoder/TextDecoder
rg -n "Blob|File|FormData|XMLHttpRequest|fetch|localStorage|sessionStorage|document|window|navigator" --type=ts src/

Repository: abdullahmujahidali/Cellify

Length of output: 52


🏁 Script executed:

#!/bin/bash
# Check TextEncoder/TextDecoder usage specifically
rg -n "TextEncoder|TextDecoder" --type=ts src/

Repository: abdullahmujahidali/Cellify

Length of output: 223


🏁 Script executed:

#!/bin/bash
# View current tsconfig.json
cat tsconfig.json

Repository: abdullahmujahidali/Cellify

Length of output: 785


🏁 Script executed:

#!/bin/bash
# Check if there's any package.json to understand TypeScript version
cat package.json | grep -A 5 typescript

Repository: abdullahmujahidali/Cellify

Length of output: 174


🏁 Script executed:

#!/bin/bash
# Check for any DOM type references in the source files
rg -n "DOM|TextEncoder|TextDecoder" src/ tsconfig.json

Repository: abdullahmujahidali/Cellify

Length of output: 398


Remove DOM lib from lib array in tsconfig.json—it is not necessary.

TextEncoder and TextDecoder, the only DOM-related features used in this codebase (csv.writer.ts and csv.reader.ts), are included in the ES2022 standard library, which is already specified. The DOM lib adds unnecessary browser-specific APIs (Blob, File, FormData, XMLHttpRequest, etc.) with zero actual usage in the codebase. Since TypeScript 5.3.0 includes these APIs in ES2022, you can safely change line 4 to "lib": ["ES2022"].

🤖 Prompt for AI Agents
In tsconfig.json around line 4, the compiler "lib" currently includes "DOM"
which is unnecessary; remove "DOM" so the lib array is only ["ES2022"]. Edit
that line to drop "DOM" (leave "ES2022") to avoid pulling in browser-only types
while keeping TextEncoder/TextDecoder from ES2022.

@abdullahmujahidali
abdullahmujahidali merged commit 5f11f2c into main Dec 15, 2025
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants