@nazarkalytiuk/rusc-xlsx 1.0.7 → 1.0.9

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 CHANGED
@@ -116,12 +116,13 @@ const worksheet = workbook.addWorksheetWithConstantMemory('Large');
116
116
  - **Memory**: Constant ~0.02 MB (regardless of size!)
117
117
  - **Limitations**: Sequential row writing only, no tables
118
118
 
119
- > **Important:** For large exports, use `addWorksheetWithConstantMemory()` with `save(filename)` — not `saveToBuffer()`. The constant memory mode flushes rows to temp files as they're written, but `saveToBuffer()` would load the entire result back into memory, defeating the purpose. Use `saveToStream()` if you need to pipe the output without disk I/O overhead.
119
+ > **Important:** For large exports, use `save(filename)` or `await saveToStream(writable)` instead of `saveToBuffer()`. `saveToStream()` is temp-file-backed: it saves to the operating system's temporary directory, pipes the file into the writable, waits for completion, and removes the temporary file. It avoids buffering the entire XLSX file in JavaScript memory, but it does use temporary disk I/O.
120
120
 
121
121
  **Example: 1 million rows**
122
122
  ```javascript
123
123
  const workbook = new Workbook();
124
124
  const worksheet = workbook.addWorksheetWithConstantMemory('Data');
125
+ worksheet.setDefaultRowHeight(15.001); // Set once instead of once per row
125
126
 
126
127
  for (let row = 0; row < 1000000; row++) {
127
128
  worksheet.write(row, 0, `Row ${row}`);
@@ -170,16 +171,17 @@ workbook.save('output.xlsx');
170
171
  - `setTempdir(path)` - Set temp directory for memory modes
171
172
  - `save(filename)` - Save to file
172
173
  - `saveToBuffer()` - Save to Buffer
174
+ - `saveToStream(writable)` - Save through a temp file and await stream completion
173
175
  - `defineName(name, formula)` - Define named range
174
176
  - `readOnlyRecommended()` - Mark as read-only recommended
175
177
  - `addVbaProject(path)` - Add VBA macros
176
178
  - `setProperties(props)` - Set document metadata
177
179
 
178
- ### Worksheet (96 methods)
180
+ ### Worksheet
179
181
  - **Writing**: `write()`, `writeString()`, `writeNumber()`, `writeBoolean()`, `writeBlank()`
180
182
  - **DateTime**: `writeDatetime()`, `writeDatetimeFromTimestamp()`, `writeDatetimeFromYmd()`, etc.
181
183
  - **Formulas**: `writeFormula()`, `writeArrayFormula()`, `writeDynamicFormula()`
182
- - **Layout**: `setColumnWidth()`, `setRowHeight()`, `mergeRange()`, `setName()`
184
+ - **Layout**: `setColumnWidth()`, `setRowHeight()`, `setDefaultRowHeight()`, `mergeRange()`, `setName()`
183
185
  - **Features**: `insertNote()`, `addDataValidation()`, `insertChart()`, `insertImage()`, `addTable()`, `insertButton()`, `insertShape()`
184
186
  - **Conditional Formatting**: 14 methods for all rule types
185
187
  - **Page Setup**: 26 methods for printing, margins, headers, etc.
package/index.d.ts CHANGED
@@ -438,14 +438,18 @@ export declare class RuscWorksheet {
438
438
  write(row: number, col: number, value: string | number | boolean, format?: RuscFormat | undefined | null): void
439
439
  /**
440
440
  * Write an array of values as a row starting at the given column.
441
- * Uses lazy iteration — reads one cell at a time from JS, null/undefined skipped.
441
+ * Uses lazy Array iteration — reads one cell at a time from the JS array
442
+ * instead of deserializing the entire row into Rust memory.
443
+ * Null/undefined values are skipped (preserving column positions).
442
444
  */
443
- writeRow(row: number, startCol: number, values: Array<string | number | boolean | null | undefined>, format?: RuscFormat | undefined | null): void
445
+ writeRow(row: number, startCol: number, values: unknown[], format?: RuscFormat | undefined | null): void
444
446
  /**
445
447
  * Write a 2D array of values starting at the given position.
446
- * Uses lazy iteration — never materializes the entire grid in Rust memory.
448
+ * Uses lazy Array iteration — reads one row/cell at a time from JS,
449
+ * never materializing the entire grid in Rust memory.
450
+ * Null/undefined values are skipped (preserving column positions).
447
451
  */
448
- writeRows(startRow: number, startCol: number, rows: Array<Array<string | number | boolean | null | undefined>>, format?: RuscFormat | undefined | null): void
452
+ writeRows(startRow: number, startCol: number, rows: unknown[], format?: RuscFormat | undefined | null): void
449
453
  /** Write a string to a cell */
450
454
  writeString(row: number, col: number, value: string): void
451
455
  /** Write a number to a cell */
@@ -472,6 +476,8 @@ export declare class RuscWorksheet {
472
476
  setColumnWidth(col: number, width: number): void
473
477
  /** Set the height of a row */
474
478
  setRowHeight(row: number, height: number): void
479
+ /** Set the default height for all worksheet rows efficiently */
480
+ setDefaultRowHeight(height: number): void
475
481
  /** Set the name of the worksheet */
476
482
  setName(name: string): void
477
483
  /** Merge a range of cells */
@@ -607,3 +613,9 @@ export declare class RuscWorksheet {
607
613
  /** Insert a shape (textbox) at the specified cell position with pixel offsets */
608
614
  insertShapeWithOffset(row: number, col: number, shape: RuscShape, xOffset: number, yOffset: number): void
609
615
  }
616
+
617
+ /** Resets peak memory tracking to current usage */
618
+ export declare function rustMemoryResetPeak(): void
619
+
620
+ /** Returns [currentBytes, peakBytes] of Rust allocator usage */
621
+ export declare function rustMemoryStats(): Array<number>
package/index.js CHANGED
@@ -77,8 +77,8 @@ function requireNative() {
77
77
  try {
78
78
  const binding = require('@nazarkalytiuk/rusc-xlsx-android-arm64')
79
79
  const bindingPackageVersion = require('@nazarkalytiuk/rusc-xlsx-android-arm64/package.json').version
80
- if (bindingPackageVersion !== '1.0.5' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
81
- throw new Error(`Native binding package version mismatch, expected 1.0.5 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
80
+ if (bindingPackageVersion !== '1.0.9' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
81
+ throw new Error(`Native binding package version mismatch, expected 1.0.9 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
82
82
  }
83
83
  return binding
84
84
  } catch (e) {
@@ -93,8 +93,8 @@ function requireNative() {
93
93
  try {
94
94
  const binding = require('@nazarkalytiuk/rusc-xlsx-android-arm-eabi')
95
95
  const bindingPackageVersion = require('@nazarkalytiuk/rusc-xlsx-android-arm-eabi/package.json').version
96
- if (bindingPackageVersion !== '1.0.5' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
97
- throw new Error(`Native binding package version mismatch, expected 1.0.5 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
96
+ if (bindingPackageVersion !== '1.0.9' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
97
+ throw new Error(`Native binding package version mismatch, expected 1.0.9 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
98
98
  }
99
99
  return binding
100
100
  } catch (e) {
@@ -114,8 +114,8 @@ function requireNative() {
114
114
  try {
115
115
  const binding = require('@nazarkalytiuk/rusc-xlsx-win32-x64-gnu')
116
116
  const bindingPackageVersion = require('@nazarkalytiuk/rusc-xlsx-win32-x64-gnu/package.json').version
117
- if (bindingPackageVersion !== '1.0.5' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
118
- throw new Error(`Native binding package version mismatch, expected 1.0.5 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
117
+ if (bindingPackageVersion !== '1.0.9' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
118
+ throw new Error(`Native binding package version mismatch, expected 1.0.9 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
119
119
  }
120
120
  return binding
121
121
  } catch (e) {
@@ -130,8 +130,8 @@ function requireNative() {
130
130
  try {
131
131
  const binding = require('@nazarkalytiuk/rusc-xlsx-win32-x64-msvc')
132
132
  const bindingPackageVersion = require('@nazarkalytiuk/rusc-xlsx-win32-x64-msvc/package.json').version
133
- if (bindingPackageVersion !== '1.0.5' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
134
- throw new Error(`Native binding package version mismatch, expected 1.0.5 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
133
+ if (bindingPackageVersion !== '1.0.9' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
134
+ throw new Error(`Native binding package version mismatch, expected 1.0.9 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
135
135
  }
136
136
  return binding
137
137
  } catch (e) {
@@ -147,8 +147,8 @@ function requireNative() {
147
147
  try {
148
148
  const binding = require('@nazarkalytiuk/rusc-xlsx-win32-ia32-msvc')
149
149
  const bindingPackageVersion = require('@nazarkalytiuk/rusc-xlsx-win32-ia32-msvc/package.json').version
150
- if (bindingPackageVersion !== '1.0.5' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
151
- throw new Error(`Native binding package version mismatch, expected 1.0.5 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
150
+ if (bindingPackageVersion !== '1.0.9' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
151
+ throw new Error(`Native binding package version mismatch, expected 1.0.9 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
152
152
  }
153
153
  return binding
154
154
  } catch (e) {
@@ -163,8 +163,8 @@ function requireNative() {
163
163
  try {
164
164
  const binding = require('@nazarkalytiuk/rusc-xlsx-win32-arm64-msvc')
165
165
  const bindingPackageVersion = require('@nazarkalytiuk/rusc-xlsx-win32-arm64-msvc/package.json').version
166
- if (bindingPackageVersion !== '1.0.5' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
167
- throw new Error(`Native binding package version mismatch, expected 1.0.5 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
166
+ if (bindingPackageVersion !== '1.0.9' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
167
+ throw new Error(`Native binding package version mismatch, expected 1.0.9 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
168
168
  }
169
169
  return binding
170
170
  } catch (e) {
@@ -182,8 +182,8 @@ function requireNative() {
182
182
  try {
183
183
  const binding = require('@nazarkalytiuk/rusc-xlsx-darwin-universal')
184
184
  const bindingPackageVersion = require('@nazarkalytiuk/rusc-xlsx-darwin-universal/package.json').version
185
- if (bindingPackageVersion !== '1.0.5' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
186
- throw new Error(`Native binding package version mismatch, expected 1.0.5 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
185
+ if (bindingPackageVersion !== '1.0.9' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
186
+ throw new Error(`Native binding package version mismatch, expected 1.0.9 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
187
187
  }
188
188
  return binding
189
189
  } catch (e) {
@@ -198,8 +198,8 @@ function requireNative() {
198
198
  try {
199
199
  const binding = require('@nazarkalytiuk/rusc-xlsx-darwin-x64')
200
200
  const bindingPackageVersion = require('@nazarkalytiuk/rusc-xlsx-darwin-x64/package.json').version
201
- if (bindingPackageVersion !== '1.0.5' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
202
- throw new Error(`Native binding package version mismatch, expected 1.0.5 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
201
+ if (bindingPackageVersion !== '1.0.9' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
202
+ throw new Error(`Native binding package version mismatch, expected 1.0.9 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
203
203
  }
204
204
  return binding
205
205
  } catch (e) {
@@ -214,8 +214,8 @@ function requireNative() {
214
214
  try {
215
215
  const binding = require('@nazarkalytiuk/rusc-xlsx-darwin-arm64')
216
216
  const bindingPackageVersion = require('@nazarkalytiuk/rusc-xlsx-darwin-arm64/package.json').version
217
- if (bindingPackageVersion !== '1.0.5' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
218
- throw new Error(`Native binding package version mismatch, expected 1.0.5 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
217
+ if (bindingPackageVersion !== '1.0.9' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
218
+ throw new Error(`Native binding package version mismatch, expected 1.0.9 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
219
219
  }
220
220
  return binding
221
221
  } catch (e) {
@@ -234,8 +234,8 @@ function requireNative() {
234
234
  try {
235
235
  const binding = require('@nazarkalytiuk/rusc-xlsx-freebsd-x64')
236
236
  const bindingPackageVersion = require('@nazarkalytiuk/rusc-xlsx-freebsd-x64/package.json').version
237
- if (bindingPackageVersion !== '1.0.5' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
238
- throw new Error(`Native binding package version mismatch, expected 1.0.5 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
237
+ if (bindingPackageVersion !== '1.0.9' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
238
+ throw new Error(`Native binding package version mismatch, expected 1.0.9 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
239
239
  }
240
240
  return binding
241
241
  } catch (e) {
@@ -250,8 +250,8 @@ function requireNative() {
250
250
  try {
251
251
  const binding = require('@nazarkalytiuk/rusc-xlsx-freebsd-arm64')
252
252
  const bindingPackageVersion = require('@nazarkalytiuk/rusc-xlsx-freebsd-arm64/package.json').version
253
- if (bindingPackageVersion !== '1.0.5' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
254
- throw new Error(`Native binding package version mismatch, expected 1.0.5 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
253
+ if (bindingPackageVersion !== '1.0.9' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
254
+ throw new Error(`Native binding package version mismatch, expected 1.0.9 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
255
255
  }
256
256
  return binding
257
257
  } catch (e) {
@@ -271,8 +271,8 @@ function requireNative() {
271
271
  try {
272
272
  const binding = require('@nazarkalytiuk/rusc-xlsx-linux-x64-musl')
273
273
  const bindingPackageVersion = require('@nazarkalytiuk/rusc-xlsx-linux-x64-musl/package.json').version
274
- if (bindingPackageVersion !== '1.0.5' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
275
- throw new Error(`Native binding package version mismatch, expected 1.0.5 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
274
+ if (bindingPackageVersion !== '1.0.9' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
275
+ throw new Error(`Native binding package version mismatch, expected 1.0.9 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
276
276
  }
277
277
  return binding
278
278
  } catch (e) {
@@ -287,8 +287,8 @@ function requireNative() {
287
287
  try {
288
288
  const binding = require('@nazarkalytiuk/rusc-xlsx-linux-x64-gnu')
289
289
  const bindingPackageVersion = require('@nazarkalytiuk/rusc-xlsx-linux-x64-gnu/package.json').version
290
- if (bindingPackageVersion !== '1.0.5' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
291
- throw new Error(`Native binding package version mismatch, expected 1.0.5 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
290
+ if (bindingPackageVersion !== '1.0.9' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
291
+ throw new Error(`Native binding package version mismatch, expected 1.0.9 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
292
292
  }
293
293
  return binding
294
294
  } catch (e) {
@@ -305,8 +305,8 @@ function requireNative() {
305
305
  try {
306
306
  const binding = require('@nazarkalytiuk/rusc-xlsx-linux-arm64-musl')
307
307
  const bindingPackageVersion = require('@nazarkalytiuk/rusc-xlsx-linux-arm64-musl/package.json').version
308
- if (bindingPackageVersion !== '1.0.5' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
309
- throw new Error(`Native binding package version mismatch, expected 1.0.5 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
308
+ if (bindingPackageVersion !== '1.0.9' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
309
+ throw new Error(`Native binding package version mismatch, expected 1.0.9 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
310
310
  }
311
311
  return binding
312
312
  } catch (e) {
@@ -321,8 +321,8 @@ function requireNative() {
321
321
  try {
322
322
  const binding = require('@nazarkalytiuk/rusc-xlsx-linux-arm64-gnu')
323
323
  const bindingPackageVersion = require('@nazarkalytiuk/rusc-xlsx-linux-arm64-gnu/package.json').version
324
- if (bindingPackageVersion !== '1.0.5' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
325
- throw new Error(`Native binding package version mismatch, expected 1.0.5 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
324
+ if (bindingPackageVersion !== '1.0.9' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
325
+ throw new Error(`Native binding package version mismatch, expected 1.0.9 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
326
326
  }
327
327
  return binding
328
328
  } catch (e) {
@@ -339,8 +339,8 @@ function requireNative() {
339
339
  try {
340
340
  const binding = require('@nazarkalytiuk/rusc-xlsx-linux-arm-musleabihf')
341
341
  const bindingPackageVersion = require('@nazarkalytiuk/rusc-xlsx-linux-arm-musleabihf/package.json').version
342
- if (bindingPackageVersion !== '1.0.5' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
343
- throw new Error(`Native binding package version mismatch, expected 1.0.5 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
342
+ if (bindingPackageVersion !== '1.0.9' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
343
+ throw new Error(`Native binding package version mismatch, expected 1.0.9 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
344
344
  }
345
345
  return binding
346
346
  } catch (e) {
@@ -355,8 +355,8 @@ function requireNative() {
355
355
  try {
356
356
  const binding = require('@nazarkalytiuk/rusc-xlsx-linux-arm-gnueabihf')
357
357
  const bindingPackageVersion = require('@nazarkalytiuk/rusc-xlsx-linux-arm-gnueabihf/package.json').version
358
- if (bindingPackageVersion !== '1.0.5' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
359
- throw new Error(`Native binding package version mismatch, expected 1.0.5 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
358
+ if (bindingPackageVersion !== '1.0.9' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
359
+ throw new Error(`Native binding package version mismatch, expected 1.0.9 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
360
360
  }
361
361
  return binding
362
362
  } catch (e) {
@@ -373,8 +373,8 @@ function requireNative() {
373
373
  try {
374
374
  const binding = require('@nazarkalytiuk/rusc-xlsx-linux-loong64-musl')
375
375
  const bindingPackageVersion = require('@nazarkalytiuk/rusc-xlsx-linux-loong64-musl/package.json').version
376
- if (bindingPackageVersion !== '1.0.5' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
377
- throw new Error(`Native binding package version mismatch, expected 1.0.5 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
376
+ if (bindingPackageVersion !== '1.0.9' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
377
+ throw new Error(`Native binding package version mismatch, expected 1.0.9 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
378
378
  }
379
379
  return binding
380
380
  } catch (e) {
@@ -389,8 +389,8 @@ function requireNative() {
389
389
  try {
390
390
  const binding = require('@nazarkalytiuk/rusc-xlsx-linux-loong64-gnu')
391
391
  const bindingPackageVersion = require('@nazarkalytiuk/rusc-xlsx-linux-loong64-gnu/package.json').version
392
- if (bindingPackageVersion !== '1.0.5' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
393
- throw new Error(`Native binding package version mismatch, expected 1.0.5 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
392
+ if (bindingPackageVersion !== '1.0.9' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
393
+ throw new Error(`Native binding package version mismatch, expected 1.0.9 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
394
394
  }
395
395
  return binding
396
396
  } catch (e) {
@@ -407,8 +407,8 @@ function requireNative() {
407
407
  try {
408
408
  const binding = require('@nazarkalytiuk/rusc-xlsx-linux-riscv64-musl')
409
409
  const bindingPackageVersion = require('@nazarkalytiuk/rusc-xlsx-linux-riscv64-musl/package.json').version
410
- if (bindingPackageVersion !== '1.0.5' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
411
- throw new Error(`Native binding package version mismatch, expected 1.0.5 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
410
+ if (bindingPackageVersion !== '1.0.9' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
411
+ throw new Error(`Native binding package version mismatch, expected 1.0.9 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
412
412
  }
413
413
  return binding
414
414
  } catch (e) {
@@ -423,8 +423,8 @@ function requireNative() {
423
423
  try {
424
424
  const binding = require('@nazarkalytiuk/rusc-xlsx-linux-riscv64-gnu')
425
425
  const bindingPackageVersion = require('@nazarkalytiuk/rusc-xlsx-linux-riscv64-gnu/package.json').version
426
- if (bindingPackageVersion !== '1.0.5' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
427
- throw new Error(`Native binding package version mismatch, expected 1.0.5 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
426
+ if (bindingPackageVersion !== '1.0.9' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
427
+ throw new Error(`Native binding package version mismatch, expected 1.0.9 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
428
428
  }
429
429
  return binding
430
430
  } catch (e) {
@@ -440,8 +440,8 @@ function requireNative() {
440
440
  try {
441
441
  const binding = require('@nazarkalytiuk/rusc-xlsx-linux-ppc64-gnu')
442
442
  const bindingPackageVersion = require('@nazarkalytiuk/rusc-xlsx-linux-ppc64-gnu/package.json').version
443
- if (bindingPackageVersion !== '1.0.5' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
444
- throw new Error(`Native binding package version mismatch, expected 1.0.5 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
443
+ if (bindingPackageVersion !== '1.0.9' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
444
+ throw new Error(`Native binding package version mismatch, expected 1.0.9 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
445
445
  }
446
446
  return binding
447
447
  } catch (e) {
@@ -456,8 +456,8 @@ function requireNative() {
456
456
  try {
457
457
  const binding = require('@nazarkalytiuk/rusc-xlsx-linux-s390x-gnu')
458
458
  const bindingPackageVersion = require('@nazarkalytiuk/rusc-xlsx-linux-s390x-gnu/package.json').version
459
- if (bindingPackageVersion !== '1.0.5' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
460
- throw new Error(`Native binding package version mismatch, expected 1.0.5 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
459
+ if (bindingPackageVersion !== '1.0.9' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
460
+ throw new Error(`Native binding package version mismatch, expected 1.0.9 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
461
461
  }
462
462
  return binding
463
463
  } catch (e) {
@@ -476,8 +476,8 @@ function requireNative() {
476
476
  try {
477
477
  const binding = require('@nazarkalytiuk/rusc-xlsx-openharmony-arm64')
478
478
  const bindingPackageVersion = require('@nazarkalytiuk/rusc-xlsx-openharmony-arm64/package.json').version
479
- if (bindingPackageVersion !== '1.0.5' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
480
- throw new Error(`Native binding package version mismatch, expected 1.0.5 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
479
+ if (bindingPackageVersion !== '1.0.9' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
480
+ throw new Error(`Native binding package version mismatch, expected 1.0.9 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
481
481
  }
482
482
  return binding
483
483
  } catch (e) {
@@ -492,8 +492,8 @@ function requireNative() {
492
492
  try {
493
493
  const binding = require('@nazarkalytiuk/rusc-xlsx-openharmony-x64')
494
494
  const bindingPackageVersion = require('@nazarkalytiuk/rusc-xlsx-openharmony-x64/package.json').version
495
- if (bindingPackageVersion !== '1.0.5' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
496
- throw new Error(`Native binding package version mismatch, expected 1.0.5 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
495
+ if (bindingPackageVersion !== '1.0.9' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
496
+ throw new Error(`Native binding package version mismatch, expected 1.0.9 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
497
497
  }
498
498
  return binding
499
499
  } catch (e) {
@@ -508,8 +508,8 @@ function requireNative() {
508
508
  try {
509
509
  const binding = require('@nazarkalytiuk/rusc-xlsx-openharmony-arm')
510
510
  const bindingPackageVersion = require('@nazarkalytiuk/rusc-xlsx-openharmony-arm/package.json').version
511
- if (bindingPackageVersion !== '1.0.5' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
512
- throw new Error(`Native binding package version mismatch, expected 1.0.5 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
511
+ if (bindingPackageVersion !== '1.0.9' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
512
+ throw new Error(`Native binding package version mismatch, expected 1.0.9 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
513
513
  }
514
514
  return binding
515
515
  } catch (e) {
@@ -588,3 +588,5 @@ module.exports.RuscTable = nativeBinding.RuscTable
588
588
  module.exports.RuscTableColumn = nativeBinding.RuscTableColumn
589
589
  module.exports.RuscWorkbook = nativeBinding.RuscWorkbook
590
590
  module.exports.RuscWorksheet = nativeBinding.RuscWorksheet
591
+ module.exports.rustMemoryResetPeak = nativeBinding.rustMemoryResetPeak
592
+ module.exports.rustMemoryStats = nativeBinding.rustMemoryStats
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nazarkalytiuk/rusc-xlsx",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "Fast Excel XLSX library for Node.js powered by rust_xlsxwriter",
5
5
  "main": "wrapper.js",
6
6
  "types": "wrapper.d.ts",
@@ -61,6 +61,7 @@
61
61
  "@napi-rs/cli": "^3.0.0",
62
62
  "@types/jest": "^29.5.12",
63
63
  "@types/node": "^20.11.19",
64
+ "adm-zip": "^0.6.0",
64
65
  "jest": "^29.7.0",
65
66
  "ts-jest": "^29.1.2",
66
67
  "typescript": "^5.3.3"
@@ -69,12 +70,12 @@
69
70
  "node": ">=16"
70
71
  },
71
72
  "optionalDependencies": {
72
- "@nazarkalytiuk/rusc-xlsx-win32-x64-msvc": "1.0.7",
73
- "@nazarkalytiuk/rusc-xlsx-win32-ia32-msvc": "1.0.7",
74
- "@nazarkalytiuk/rusc-xlsx-win32-arm64-msvc": "1.0.7",
75
- "@nazarkalytiuk/rusc-xlsx-darwin-universal": "1.0.7",
76
- "@nazarkalytiuk/rusc-xlsx-linux-x64-gnu": "1.0.7",
77
- "@nazarkalytiuk/rusc-xlsx-linux-arm64-gnu": "1.0.7",
78
- "@nazarkalytiuk/rusc-xlsx-linux-x64-musl": "1.0.7"
73
+ "@nazarkalytiuk/rusc-xlsx-win32-x64-msvc": "1.0.9",
74
+ "@nazarkalytiuk/rusc-xlsx-win32-ia32-msvc": "1.0.9",
75
+ "@nazarkalytiuk/rusc-xlsx-win32-arm64-msvc": "1.0.9",
76
+ "@nazarkalytiuk/rusc-xlsx-darwin-universal": "1.0.9",
77
+ "@nazarkalytiuk/rusc-xlsx-linux-x64-gnu": "1.0.9",
78
+ "@nazarkalytiuk/rusc-xlsx-linux-arm64-gnu": "1.0.9",
79
+ "@nazarkalytiuk/rusc-xlsx-linux-x64-musl": "1.0.9"
79
80
  }
80
81
  }
package/wrapper.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  // TypeScript definitions for wrapper.js
2
2
  // These provide the fluent API with method chaining
3
3
 
4
+ import type { Writable } from 'stream';
5
+
4
6
  /** Color value - can be a named color or hex code */
5
7
  export type Color =
6
8
  | 'black' | 'blue' | 'brown' | 'cyan' | 'gray' | 'green'
@@ -844,6 +846,12 @@ export declare class Worksheet {
844
846
  */
845
847
  setRowHeight(row: number, height: number): void;
846
848
 
849
+ /**
850
+ * Set the default height for all worksheet rows without per-row metadata
851
+ * @param height - Height in points
852
+ */
853
+ setDefaultRowHeight(height: number): void;
854
+
847
855
  /**
848
856
  * Set the worksheet name
849
857
  * @param name - Worksheet name
@@ -2278,22 +2286,24 @@ export declare class Workbook {
2278
2286
  /**
2279
2287
  * Save the workbook to a Writable stream
2280
2288
  *
2281
- * Streams XLSX data directly to the writable without buffering the entire
2282
- * file in memory. Combines the speed of `saveToBuffer()` with the low
2283
- * memory footprint of `save(filename)`.
2289
+ * Saves the workbook to a temporary file, then pipes that file into the
2290
+ * writable without buffering the entire XLSX file in JavaScript memory.
2291
+ * The temporary file is removed after the pipeline succeeds or fails.
2292
+ * The promise rejects on native save, read, writable, pipeline, or cleanup errors.
2284
2293
  *
2285
2294
  * @param writable - A Node.js Writable stream (e.g., fs.createWriteStream, HTTP response)
2295
+ * @returns A promise that settles after streaming and temporary-file cleanup complete
2286
2296
  * @example
2287
2297
  * const fs = require('fs');
2288
2298
  * const stream = fs.createWriteStream('output.xlsx');
2289
- * workbook.saveToStream(stream);
2299
+ * await workbook.saveToStream(stream);
2290
2300
  *
2291
2301
  * @example
2292
2302
  * // HTTP response
2293
2303
  * res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
2294
- * workbook.saveToStream(res);
2304
+ * await workbook.saveToStream(res);
2295
2305
  */
2296
- saveToStream(writable: import('stream').Writable): void;
2306
+ saveToStream(writable: Writable): Promise<void>;
2297
2307
 
2298
2308
  /**
2299
2309
  * Define a named range or formula
@@ -2332,5 +2342,26 @@ export declare class Workbook {
2332
2342
  setProperties(properties: DocProperties): void;
2333
2343
  }
2334
2344
 
2345
+ /**
2346
+ * Returns [currentBytes, peakBytes] of Rust allocator usage.
2347
+ * Useful for profiling memory consumption of the native layer.
2348
+ *
2349
+ * @example
2350
+ * const [current, peak] = rustMemoryStats();
2351
+ * console.log(`Rust heap: ${(current / 1024 / 1024).toFixed(2)} MB (peak: ${(peak / 1024 / 1024).toFixed(2)} MB)`);
2352
+ */
2353
+ export declare function rustMemoryStats(): [number, number];
2354
+
2355
+ /**
2356
+ * Resets peak memory tracking to the current allocation level.
2357
+ * Call before a section you want to measure.
2358
+ *
2359
+ * @example
2360
+ * rustMemoryResetPeak();
2361
+ * // ... do work ...
2362
+ * const [current, peak] = rustMemoryStats();
2363
+ */
2364
+ export declare function rustMemoryResetPeak(): void;
2365
+
2335
2366
  // Re-export native bindings for advanced use
2336
2367
  export { RuscFormat, RuscNote, RuscFormula, RuscDataValidation, RuscChart, RuscWorkbook, RuscWorksheet, RuscProtectionOptions, RuscRichText, RuscImage, RuscTable, RuscTableColumn, RuscSparkline, RuscDocProperties, RuscButton, RuscShape } from './index';
package/wrapper.js CHANGED
@@ -577,6 +577,10 @@ class Worksheet {
577
577
  return this._native.setRowHeight(row, height)
578
578
  }
579
579
 
580
+ setDefaultRowHeight(height) {
581
+ return this._native.setDefaultRowHeight(height)
582
+ }
583
+
580
584
  setName(name) {
581
585
  return this._native.setName(name)
582
586
  }
@@ -1271,23 +1275,40 @@ class Workbook {
1271
1275
  return this._native.saveToBuffer()
1272
1276
  }
1273
1277
 
1274
- saveToStream(writable) {
1278
+ async saveToStream(writable) {
1275
1279
  const os = require('os')
1276
1280
  const path = require('path')
1277
1281
  const fs = require('fs')
1278
1282
  const crypto = require('crypto')
1283
+ const { pipeline } = require('stream/promises')
1279
1284
 
1280
1285
  const tmpFile = path.join(os.tmpdir(), `rusc-xlsx-${crypto.randomBytes(8).toString('hex')}.xlsx`)
1281
- this._native.save(tmpFile)
1286
+ let operationError
1287
+
1288
+ try {
1289
+ this._native.save(tmpFile)
1290
+ await pipeline(fs.createReadStream(tmpFile), writable)
1291
+ } catch (error) {
1292
+ operationError = error
1293
+ }
1282
1294
 
1283
- const readable = fs.createReadStream(tmpFile)
1284
- readable.on('end', () => {
1285
- fs.unlink(tmpFile, () => {})
1286
- })
1287
- readable.on('error', () => {
1288
- fs.unlink(tmpFile, () => {})
1289
- })
1290
- readable.pipe(writable)
1295
+ try {
1296
+ await fs.promises.unlink(tmpFile)
1297
+ } catch (cleanupError) {
1298
+ if (cleanupError.code !== 'ENOENT') {
1299
+ if (operationError) {
1300
+ throw new AggregateError(
1301
+ [operationError, cleanupError],
1302
+ 'Failed to save workbook to stream and remove the temporary file'
1303
+ )
1304
+ }
1305
+ throw cleanupError
1306
+ }
1307
+ }
1308
+
1309
+ if (operationError) {
1310
+ throw operationError
1311
+ }
1291
1312
  }
1292
1313
 
1293
1314
  defineName(name, formula) {
@@ -1342,4 +1363,7 @@ module.exports = {
1342
1363
  RuscDocProperties: nativeBinding.RuscDocProperties,
1343
1364
  RuscButton: nativeBinding.RuscButton,
1344
1365
  RuscShape: nativeBinding.RuscShape,
1366
+ // Memory tracking
1367
+ rustMemoryStats: nativeBinding.rustMemoryStats,
1368
+ rustMemoryResetPeak: nativeBinding.rustMemoryResetPeak,
1345
1369
  }