igir
Version:
🕹 A zero-setup ROM collection manager that sorts, filters, extracts or archives, patches, and reports on collections of any size on any OS.
88 lines (87 loc) • 2.32 kB
JavaScript
import stream from 'node:stream';
import zlib from '../../zlib-1.1.3/index.js';
/**
* A Transform stream that compresses data using zlib.
*/
export default class ZlibCompressTransform extends stream.Transform {
deflater = new zlib.Deflater(9);
deflaterEnded = false;
constructor() {
super();
// Set up cleanup handlers
this.on('error', () => {
this.cleanup();
});
this.on('close', () => {
this.cleanup();
});
}
/**
* Deflate the chunk and emit the result.
*/
_transform(chunk, _encoding, callback) {
try {
if (this.deflaterEnded) {
callback(new Error('cannot compress after the deflater has been ended'));
return;
}
const compressedChunk = this.deflater.compressChunk(chunk);
if (compressedChunk.length > 0) {
this.push(compressedChunk);
}
callback();
}
catch (error) {
this.cleanup();
callback(error instanceof Error ? error : new Error(String(error)));
}
}
/**
* Close the zlib deflater when the stream ends.
*/
_flush(callback) {
try {
this.finalizeDeflater();
callback();
}
catch (error) {
callback(error instanceof Error ? error : new Error(String(error)));
}
}
/**
* Clean up resources when stream.destroy() is called.
*/
_destroy(err, callback) {
try {
this.cleanup();
callback(err);
}
catch (cleanupError) {
callback(cleanupError instanceof Error ? cleanupError : new Error(String(cleanupError)));
}
}
/**
* Clean up method to be called when the stream ends.
*/
cleanup() {
try {
this.finalizeDeflater();
}
catch {
/* ignored */
}
}
/**
* Finalize the deflater and emit the final output.
*/
finalizeDeflater() {
if (this.deflaterEnded) {
return;
}
this.deflaterEnded = true;
const finalChunk = this.deflater.end();
if (finalChunk.length > 0) {
this.push(finalChunk);
}
}
}