@xlsxflow/core 1.1.4 → 1.1.5

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/dist/index.mjs CHANGED
@@ -56,21 +56,34 @@ class ZipStreamWriter {
56
56
  // Stream data, tracking sizes and CRC32
57
57
  let uncompressedSize = 0;
58
58
  let crc = 0xffffffff;
59
- const crcStream = new TransformStream({
60
- // CompressionStream takes every write at once, so the input is held back here instead,
61
- // while nobody reads the output
62
- transform: async (chunk, controller) => {
63
- await this.roomInQueue();
64
- uncompressedSize += chunk.length;
65
- crc = crc32Update(crc, chunk);
66
- controller.enqueue(chunk);
59
+ const compressor = new CompressionStream('deflate-raw');
60
+ const writer = compressor.writable.getWriter();
61
+ const reader = compressor.readable.getReader();
62
+ const input = inputStream.getReader();
63
+ // Node's and Bun's CompressionStream accept thousands of writes without backpressure, so one chunk
64
+ // is fed at a time: a write resolves once the chunk is compressed, which waits while nobody reads
65
+ // the output. Rows are then only pulled as fast as the ZIP is consumed.
66
+ const feed = (async () => {
67
+ try {
68
+ while (true) {
69
+ const { done, value } = await input.read();
70
+ if (done)
71
+ break;
72
+ await this.roomInQueue();
73
+ uncompressedSize += value.length;
74
+ crc = crc32Update(crc, value);
75
+ await writer.write(value);
76
+ }
77
+ await writer.close();
67
78
  }
68
- });
79
+ catch (err) {
80
+ // Stop the source too (a row generator's finally runs, a database cursor closes)
81
+ await input.cancel(err).catch(() => { });
82
+ await writer.abort(err).catch(() => { });
83
+ throw err;
84
+ }
85
+ })();
69
86
  let compressedSize = 0;
70
- const reader = inputStream
71
- .pipeThrough(crcStream)
72
- .pipeThrough(new CompressionStream('deflate-raw'))
73
- .getReader();
74
87
  try {
75
88
  while (true) {
76
89
  const { done, value } = await reader.read();
@@ -79,10 +92,12 @@ class ZipStreamWriter {
79
92
  compressedSize += value.length;
80
93
  await this.pushChunk(value);
81
94
  }
95
+ await feed;
82
96
  }
83
97
  catch (err) {
84
- // Stop the source too (a row generator's finally runs, a database cursor closes)
85
98
  await reader.cancel(err).catch(() => { });
99
+ await input.cancel(err).catch(() => { });
100
+ await feed.catch(() => { });
86
101
  throw err;
87
102
  }
88
103
  crc = (crc ^ 0xffffffff) >>> 0;
@@ -3856,6 +3871,10 @@ class SheetWriter {
3856
3871
  const box = parseRange$1(table.ref, 'table range');
3857
3872
  if (boxes.some(b => overlaps(b, box)))
3858
3873
  throw new Error(`Table "${table.name}" overlaps another table on sheet "${sheet.name}".`);
3874
+ // Excel tables cannot hold merged cells: it repairs the file by removing the table
3875
+ const merge = sheet.options.mergeCells?.find(ref => overlaps(parseRange$1(ref, 'merge range'), box));
3876
+ if (merge)
3877
+ throw new Error(`Merge "${merge}" overlaps table "${table.name}" on sheet "${sheet.name}"; Excel tables cannot contain merged cells.`);
3859
3878
  boxes.push(box);
3860
3879
  const first = colIndex(m[1]);
3861
3880
  const width = colIndex(m[3]) - first + 1;
@@ -4357,8 +4376,18 @@ function createBlobReader(blob) {
4357
4376
  return new Uint8Array(await slice.arrayBuffer());
4358
4377
  },
4359
4378
  stream(offset, length) {
4360
- const slice = blob.slice(offset, offset + length);
4361
- return slice.stream();
4379
+ // Bun's Blob.slice(start, end).stream() runs on to the end of the original blob, so stop at length
4380
+ let left = length;
4381
+ return blob.slice(offset, offset + length).stream().pipeThrough(new TransformStream({
4382
+ start(controller) { if (left <= 0)
4383
+ controller.terminate(); },
4384
+ transform(chunk, controller) {
4385
+ controller.enqueue(chunk.length > left ? chunk.subarray(0, left) : chunk);
4386
+ left -= chunk.length;
4387
+ if (left <= 0)
4388
+ controller.terminate();
4389
+ }
4390
+ }));
4362
4391
  },
4363
4392
  async close() { }
4364
4393
  };