Skip to content

Commit f88fec1

Browse files
committed
Add support for deflate/deflate-raw streams
1 parent 3334fae commit f88fec1

3 files changed

Lines changed: 118 additions & 2 deletions

File tree

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,14 @@ Each method accepts a buffer and returns a promise for a buffer.
6161

6262
## Streaming methods
6363

64-
This library also supports streaming decoding, using web de(compression) streams wherever possible.
64+
This library also supports streaming encoding and decoding, returning web-standard `TransformStream` instances. This uses native `CompressionStream`/`DecompressionStream` where available (all modern browsers and Node 18+).
6565

6666
* `createGzipStream`
6767
* `createGunzipStream`
68+
* `createDeflateStream`
69+
* `createInflateStream`
70+
* `createDeflateRawStream`
71+
* `createInflateRawStream`
6872

6973
## Browser usage
7074

src/index.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,42 @@ export function createGunzipStream(): TransformStream<BufferSource, Uint8Array>
146146
return getDuplex().toWeb(zlib.createGunzip()) as TransformStream<BufferSource, Uint8Array>;
147147
}
148148

149+
export function createDeflateStream(): TransformStream<BufferSource, Uint8Array> {
150+
// Use native CompressionStream where available:
151+
if (typeof CompressionStream !== 'undefined') {
152+
return new CompressionStream('deflate');
153+
}
154+
// Turn zlib node built-in into a web stream if not:
155+
return getDuplex().toWeb(zlib.createDeflate()) as TransformStream<BufferSource, Uint8Array>;
156+
}
157+
158+
export function createInflateStream(): TransformStream<BufferSource, Uint8Array> {
159+
// Use native DecompressionStream where available:
160+
if (typeof DecompressionStream !== 'undefined') {
161+
return new DecompressionStream('deflate');
162+
}
163+
// Turn zlib node built-in into a web stream if not:
164+
return getDuplex().toWeb(zlib.createInflate()) as TransformStream<BufferSource, Uint8Array>;
165+
}
166+
167+
export function createDeflateRawStream(): TransformStream<BufferSource, Uint8Array> {
168+
// Use native CompressionStream where available:
169+
if (typeof CompressionStream !== 'undefined') {
170+
return new CompressionStream('deflate-raw');
171+
}
172+
// Turn zlib node built-in into a web stream if not:
173+
return getDuplex().toWeb(zlib.createDeflateRaw()) as TransformStream<BufferSource, Uint8Array>;
174+
}
175+
176+
export function createInflateRawStream(): TransformStream<BufferSource, Uint8Array> {
177+
// Use native DecompressionStream where available:
178+
if (typeof DecompressionStream !== 'undefined') {
179+
return new DecompressionStream('deflate-raw');
180+
}
181+
// Turn zlib node built-in into a web stream if not:
182+
return getDuplex().toWeb(zlib.createInflateRaw()) as TransformStream<BufferSource, Uint8Array>;
183+
}
184+
149185
// --- Buffer helpers ---
150186

151187
const asBuffer = (input: Buffer | Uint8Array | ArrayBuffer): Buffer => {

test/stream.spec.ts

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ const expect = chai.expect;
55

66
import {
77
createGzipStream,
8-
createGunzipStream
8+
createGunzipStream,
9+
createDeflateStream,
10+
createInflateStream,
11+
createDeflateRawStream,
12+
createInflateRawStream
913
} from '../src/index';
1014

1115
// Helper to collect all chunks from a ReadableStream into a single Uint8Array
@@ -121,4 +125,76 @@ describe("Streaming", () => {
121125
expect(decompressed.toString()).to.equal(repeated);
122126
});
123127
});
128+
129+
describe("Deflate", () => {
130+
it('should compress data with deflate stream', async () => {
131+
const input = Buffer.from('Hello streaming deflate world!');
132+
const inputStream = createReadableStream(input);
133+
134+
const compressedStream = inputStream.pipeThrough(createDeflateStream());
135+
const compressed = await collectStream(compressedStream);
136+
137+
// Verify the compressed data can be decompressed with zlib
138+
const decompressed = zlib.inflateSync(Buffer.from(compressed));
139+
expect(decompressed.toString()).to.equal('Hello streaming deflate world!');
140+
});
141+
142+
it('should decompress deflate data with stream', async () => {
143+
const original = 'Hello streaming inflate world!';
144+
const compressed = zlib.deflateSync(original);
145+
const inputStream = createReadableStream(compressed);
146+
147+
const decompressedStream = inputStream.pipeThrough(createInflateStream());
148+
const decompressed = await collectStream(decompressedStream);
149+
150+
expect(Buffer.from(decompressed).toString()).to.equal(original);
151+
});
152+
153+
it('should handle round-trip compression and decompression', async () => {
154+
const original = 'Round-trip deflate streaming test with some repeated data data data data';
155+
const inputStream = createReadableStream(Buffer.from(original));
156+
157+
const compressedStream = inputStream.pipeThrough(createDeflateStream());
158+
const decompressedStream = compressedStream.pipeThrough(createInflateStream());
159+
const result = await collectStream(decompressedStream);
160+
161+
expect(Buffer.from(result).toString()).to.equal(original);
162+
});
163+
});
164+
165+
describe("Deflate-Raw", () => {
166+
it('should compress data with deflate-raw stream', async () => {
167+
const input = Buffer.from('Hello streaming deflate-raw world!');
168+
const inputStream = createReadableStream(input);
169+
170+
const compressedStream = inputStream.pipeThrough(createDeflateRawStream());
171+
const compressed = await collectStream(compressedStream);
172+
173+
// Verify the compressed data can be decompressed with zlib
174+
const decompressed = zlib.inflateRawSync(Buffer.from(compressed));
175+
expect(decompressed.toString()).to.equal('Hello streaming deflate-raw world!');
176+
});
177+
178+
it('should decompress deflate-raw data with stream', async () => {
179+
const original = 'Hello streaming inflate-raw world!';
180+
const compressed = zlib.deflateRawSync(original);
181+
const inputStream = createReadableStream(compressed);
182+
183+
const decompressedStream = inputStream.pipeThrough(createInflateRawStream());
184+
const decompressed = await collectStream(decompressedStream);
185+
186+
expect(Buffer.from(decompressed).toString()).to.equal(original);
187+
});
188+
189+
it('should handle round-trip compression and decompression', async () => {
190+
const original = 'Round-trip deflate-raw streaming test with some repeated data data data data';
191+
const inputStream = createReadableStream(Buffer.from(original));
192+
193+
const compressedStream = inputStream.pipeThrough(createDeflateRawStream());
194+
const decompressedStream = compressedStream.pipeThrough(createInflateRawStream());
195+
const result = await collectStream(decompressedStream);
196+
197+
expect(Buffer.from(result).toString()).to.equal(original);
198+
});
199+
});
124200
});

0 commit comments

Comments
 (0)