144 lines
3.4 KiB
TypeScript
144 lines
3.4 KiB
TypeScript
import * as plugins from './plugins.js';
|
|
import type { TCompressionLevel } from './interfaces.js';
|
|
|
|
/**
|
|
* Transform stream for GZIP compression using fflate
|
|
*/
|
|
export class GzipCompressionTransform extends plugins.stream.Transform {
|
|
private gzip: plugins.fflate.Gzip;
|
|
|
|
constructor(level: TCompressionLevel = 6) {
|
|
super();
|
|
|
|
// Create a streaming Gzip compressor
|
|
this.gzip = new plugins.fflate.Gzip({ level }, (chunk, final) => {
|
|
this.push(Buffer.from(chunk));
|
|
if (final) {
|
|
this.push(null);
|
|
}
|
|
});
|
|
}
|
|
|
|
_transform(
|
|
chunk: Buffer,
|
|
encoding: BufferEncoding,
|
|
callback: plugins.stream.TransformCallback
|
|
): void {
|
|
try {
|
|
this.gzip.push(chunk, false);
|
|
callback();
|
|
} catch (err) {
|
|
callback(err as Error);
|
|
}
|
|
}
|
|
|
|
_flush(callback: plugins.stream.TransformCallback): void {
|
|
try {
|
|
this.gzip.push(new Uint8Array(0), true);
|
|
callback();
|
|
} catch (err) {
|
|
callback(err as Error);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Transform stream for GZIP decompression using fflate
|
|
*/
|
|
export class GzipDecompressionTransform extends plugins.stream.Transform {
|
|
private gunzip: plugins.fflate.Gunzip;
|
|
|
|
constructor() {
|
|
super();
|
|
|
|
// Create a streaming Gunzip decompressor
|
|
this.gunzip = new plugins.fflate.Gunzip((chunk, final) => {
|
|
this.push(Buffer.from(chunk));
|
|
if (final) {
|
|
this.push(null);
|
|
}
|
|
});
|
|
}
|
|
|
|
_transform(
|
|
chunk: Buffer,
|
|
encoding: BufferEncoding,
|
|
callback: plugins.stream.TransformCallback
|
|
): void {
|
|
try {
|
|
this.gunzip.push(chunk, false);
|
|
callback();
|
|
} catch (err) {
|
|
callback(err as Error);
|
|
}
|
|
}
|
|
|
|
_flush(callback: plugins.stream.TransformCallback): void {
|
|
try {
|
|
this.gunzip.push(new Uint8Array(0), true);
|
|
callback();
|
|
} catch (err) {
|
|
callback(err as Error);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* GZIP compression and decompression utilities
|
|
*/
|
|
export class GzipTools {
|
|
/**
|
|
* Get a streaming compression transform
|
|
*/
|
|
public getCompressionStream(level?: TCompressionLevel): plugins.stream.Transform {
|
|
return new GzipCompressionTransform(level);
|
|
}
|
|
|
|
/**
|
|
* Get a streaming decompression transform
|
|
*/
|
|
public getDecompressionStream(): plugins.stream.Transform {
|
|
return new GzipDecompressionTransform();
|
|
}
|
|
|
|
/**
|
|
* Compress data synchronously
|
|
*/
|
|
public compressSync(data: Buffer, level?: TCompressionLevel): Buffer {
|
|
const options = level !== undefined ? { level } : undefined;
|
|
return Buffer.from(plugins.fflate.gzipSync(data, options));
|
|
}
|
|
|
|
/**
|
|
* Decompress data synchronously
|
|
*/
|
|
public decompressSync(data: Buffer): Buffer {
|
|
return Buffer.from(plugins.fflate.gunzipSync(data));
|
|
}
|
|
|
|
/**
|
|
* Compress data asynchronously
|
|
*/
|
|
public async compress(data: Buffer, level?: TCompressionLevel): Promise<Buffer> {
|
|
return new Promise((resolve, reject) => {
|
|
const options = level !== undefined ? { level } : undefined;
|
|
plugins.fflate.gzip(data, options as plugins.fflate.AsyncGzipOptions, (err, result) => {
|
|
if (err) reject(err);
|
|
else resolve(Buffer.from(result));
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Decompress data asynchronously
|
|
*/
|
|
public async decompress(data: Buffer): Promise<Buffer> {
|
|
return new Promise((resolve, reject) => {
|
|
plugins.fflate.gunzip(data, (err, result) => {
|
|
if (err) reject(err);
|
|
else resolve(Buffer.from(result));
|
|
});
|
|
});
|
|
}
|
|
}
|