Skip to content

feat: add OpenOptions for partial workbook reading#19

Merged
Nebu1eto merged 3 commits into
mainfrom
dev/phase-b-read-options
Feb 10, 2026
Merged

feat: add OpenOptions for partial workbook reading#19
Nebu1eto merged 3 commits into
mainfrom
dev/phase-b-read-options

Conversation

@Nebu1eto

Copy link
Copy Markdown
Owner

Summary

  • Add OpenOptions struct (Rust) / JsOpenOptions type (TypeScript) for controlling workbook parsing at open time
  • sheet_rows: Limit the number of rows read per sheet (like SheetJS sheetRows). Rows beyond the limit are discarded during parsing for a real performance benefit.
  • sheets: Only parse selected sheets by name. Unselected sheets exist in the workbook but contain no data (their XML is skipped entirely).
  • max_unzip_size / max_zip_entries: ZIP safety limits to prevent zip bombs. Exceed either limit and the open call returns an error.
  • New error variants: ZipSizeExceeded, ZipEntryCountExceeded
  • All existing open() / openSync() / openBuffer() / openBufferSync() methods accept an optional options parameter -- fully backward compatible
  • Rust: Workbook::open_with_options(path, &opts) and Workbook::open_from_buffer_with_options(data, &opts)
  • 17 new Rust tests + 13 new Node.js tests covering all option fields and combinations
  • API reference docs updated in both EN and KO

Test plan

  • cargo build --workspace passes
  • cargo test --workspace passes (1253 core + 178 xml + 7 integration + 1 facade + 5 doc = 1444 total)
  • cargo clippy --workspace passes (no warnings)
  • cargo fmt --check passes
  • pnpm build passes (napi + typecheck + tsdown)
  • pnpm vitest run passes (267 tests including 13 new open options tests)
  • pnpm biome check . passes
  • pnpm tsc --noEmit passes
  • No .claude/ files committed

Generated with Claude Code

@claude

claude Bot commented Feb 10, 2026

Copy link
Copy Markdown

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

@Nebu1eto Nebu1eto left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Review finding (blocking): OpenOptions sheets filtering currently swaps unselected worksheets to WorksheetXml::default() during open, and save then writes those empty worksheets back. This makes open_with_options(...).save(...) data-destructive for skipped sheets.

Relevant path: crates/sheetkit-core/src/workbook/io.rs (sheet parse branch that uses WorksheetXml::default(), and full worksheet write path).

Suggested fix: preserve raw XML bytes for unparsed sheets (or forbid save when selective parsing was used) so skipped sheets round-trip without data loss.

@Nebu1eto Nebu1eto left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Detailed review notes (blocking):

OpenOptions is a valuable addition, but there is a data-loss path today.

Blocking concern:

  • With selective sheet parsing (sheets option), unselected worksheets are replaced by WorksheetXml::default() during open.
  • A subsequent save writes those default/empty worksheets back, which destroys data on skipped sheets.

Relevant area:

  • crates/sheetkit-core/src/workbook/io.rs (sheet parse branch + normal worksheet serialization path).

Expected behavior for safety:

  • Either preserve raw XML bytes for unparsed sheets and round-trip them unchanged, or
  • mark workbook as partially loaded and reject save unless explicitly forced.

Please add a regression test for: open_with_options(select subset) -> save -> reopen -> skipped sheet data remains intact.

Nebu1eto and others added 3 commits February 10, 2026 17:02
…safety)

Add OpenOptions struct with sheet_rows, sheets, max_unzip_size, and
max_zip_entries fields. Workbook::open_with_options and
open_from_buffer_with_options accept these options to control parsing.

- sheet_rows: truncate rows per sheet during open for faster partial reads
- sheets: skip XML parsing for unselected sheets (empty WorksheetXml)
- max_unzip_size / max_zip_entries: reject archives exceeding safety limits
- New error variants: ZipSizeExceeded, ZipEntryCountExceeded
- Node.js: optional options parameter added to open/openSync/openBuffer/openBufferSync
- TypeScript wrapper updated with JsOpenOptions type
- 17 Rust tests + 13 Node.js tests covering all options and combinations
- EN and KO API reference docs updated

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When opening with selective sheet parsing (sheets option), unparsed
sheets were replaced with WorksheetXml::default(), destroying their
data on save. Now the raw XML bytes are stored and written back
directly during save, preserving all sheet content unchanged.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Nebu1eto
Nebu1eto force-pushed the dev/phase-b-read-options branch from 32d9445 to 7606c64 Compare February 10, 2026 08:07
@Nebu1eto
Nebu1eto merged commit c56eb50 into main Feb 10, 2026
3 checks passed
@Nebu1eto
Nebu1eto deleted the dev/phase-b-read-options branch February 10, 2026 08:08
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.

1 participant