@xlsxflow/core 1.1.5 → 1.1.7

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
@@ -11,6 +11,15 @@ const CRC_TABLE = (() => {
11
11
  function crc32(bytes) {
12
12
  return (crc32Update(0xffffffff, bytes) ^ 0xffffffff) >>> 0;
13
13
  }
14
+ // Older runtimes lack CompressionStream or its 'deflate-raw' format; say what is needed instead of a bare ReferenceError
15
+ function deflateRaw(kind) {
16
+ try {
17
+ return (kind === 'compress' ? new CompressionStream('deflate-raw') : new DecompressionStream('deflate-raw'));
18
+ }
19
+ catch {
20
+ throw new Error(`XlsxFlow needs ${kind === 'compress' ? 'CompressionStream' : 'DecompressionStream'} with 'deflate-raw': Chrome 103+, Firefox 113+, Safari 16.4+, Node 20.12+, Deno, Bun or Cloudflare Workers`);
21
+ }
22
+ }
14
23
  // Running CRC-32 over chunks: start at 0xffffffff, finish with (crc ^ 0xffffffff) >>> 0
15
24
  function crc32Update(crc, bytes) {
16
25
  for (let i = 0; i < bytes.length; i++)
@@ -56,13 +65,15 @@ class ZipStreamWriter {
56
65
  // Stream data, tracking sizes and CRC32
57
66
  let uncompressedSize = 0;
58
67
  let crc = 0xffffffff;
59
- const compressor = new CompressionStream('deflate-raw');
68
+ const compressor = deflateRaw('compress');
60
69
  const writer = compressor.writable.getWriter();
61
70
  const reader = compressor.readable.getReader();
62
71
  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
72
+ // Node's and Bun's CompressionStream accept thousands of writes without backpressure, so only a few
73
+ // chunks are fed ahead: a write resolves once the chunk is compressed, which waits while nobody reads
65
74
  // the output. Rows are then only pulled as fast as the ZIP is consumed.
75
+ // A few writes in flight keep the compressor busy while the next chunk is built
76
+ const inFlight = [];
66
77
  const feed = (async () => {
67
78
  try {
68
79
  while (true) {
@@ -72,8 +83,13 @@ class ZipStreamWriter {
72
83
  await this.roomInQueue();
73
84
  uncompressedSize += value.length;
74
85
  crc = crc32Update(crc, value);
75
- await writer.write(value);
86
+ const written = writer.write(value);
87
+ written.catch(() => { }); // after a failure, writes nobody awaits any more must not go unhandled
88
+ inFlight.push(written);
89
+ if (inFlight.length >= 4)
90
+ await inFlight.shift();
76
91
  }
92
+ await Promise.all(inFlight);
77
93
  await writer.close();
78
94
  }
79
95
  catch (err) {
@@ -496,7 +512,7 @@ class ZipRandomAccessParser {
496
512
  }
497
513
  const stream = await this.extractRawStream(filename);
498
514
  const data = record.compressionMethod === 0 ? stream
499
- : stream.pipeThrough(new DecompressionStream('deflate-raw'));
515
+ : stream.pipeThrough(deflateRaw('decompress'));
500
516
  // Node reports bad deflate data as a bare TypeError; name the entry instead
501
517
  const inflated = data.getReader();
502
518
  let total = 0;