Files
smartarchive/ts/classes.archiveanalyzer.ts

106 lines
3.2 KiB
TypeScript
Raw Normal View History

2023-11-06 18:14:21 +01:00
import type { SmartArchive } from './classes.smartarchive.js';
import type { TSupportedMime } from './interfaces.js';
2023-11-06 18:14:21 +01:00
import * as plugins from './plugins.js';
/**
* Type for decompression streams
*/
export type TDecompressionStream =
| plugins.stream.Transform
| plugins.stream.Duplex
| plugins.tarStream.Extract;
/**
* Result of archive analysis
*/
2023-11-06 18:14:21 +01:00
export interface IAnalyzedResult {
fileType: plugins.fileType.FileTypeResult | undefined;
2023-11-06 18:14:21 +01:00
isArchive: boolean;
resultStream: plugins.smartstream.SmartDuplex<Buffer, Buffer>;
decompressionStream: TDecompressionStream;
2023-11-06 18:14:21 +01:00
}
/**
* Analyzes archive streams to detect format and provide decompression
*/
2023-11-06 18:14:21 +01:00
export class ArchiveAnalyzer {
private smartArchiveRef: SmartArchive;
2023-11-06 18:14:21 +01:00
constructor(smartArchiveRefArg: SmartArchive) {
this.smartArchiveRef = smartArchiveRefArg;
}
/**
* Check if a MIME type represents an archive format
*/
private async mimeTypeIsArchive(mimeType: string | undefined): Promise<boolean> {
if (!mimeType) return false;
2023-11-06 18:14:21 +01:00
const archiveMimeTypes: Set<string> = new Set([
'application/zip',
'application/x-rar-compressed',
'application/x-tar',
'application/gzip',
'application/x-7z-compressed',
'application/x-bzip2',
]);
2023-11-06 18:14:21 +01:00
return archiveMimeTypes.has(mimeType);
}
/**
* Get the appropriate decompression stream for a MIME type
*/
private async getDecompressionStream(mimeTypeArg: TSupportedMime): Promise<TDecompressionStream> {
2023-11-06 18:14:21 +01:00
switch (mimeTypeArg) {
case 'application/gzip':
return this.smartArchiveRef.gzipTools.getDecompressionStream();
2024-03-17 00:29:42 +01:00
case 'application/zip':
return this.smartArchiveRef.zipTools.getDecompressionStream();
2023-11-06 18:14:21 +01:00
case 'application/x-bzip2':
return this.smartArchiveRef.bzip2Tools.getDecompressionStream();
2023-11-06 18:14:21 +01:00
case 'application/x-tar':
return this.smartArchiveRef.tarTools.getDecompressionStream();
2023-11-06 18:14:21 +01:00
default:
// Handle unsupported formats or no decompression needed
2023-11-13 22:11:24 +01:00
return plugins.smartstream.createPassThrough();
2023-11-06 18:14:21 +01:00
}
}
/**
* Create an analyzed stream that detects archive type and provides decompression
* Emits a single IAnalyzedResult object
*/
public getAnalyzedStream(): plugins.smartstream.SmartDuplex<Buffer, IAnalyzedResult> {
2023-11-06 18:14:21 +01:00
let firstRun = true;
2023-11-13 22:11:24 +01:00
const resultStream = plugins.smartstream.createPassThrough();
const analyzerstream = new plugins.smartstream.SmartDuplex<Buffer, IAnalyzedResult>({
2023-11-06 18:14:21 +01:00
readableObjectMode: true,
2023-11-08 17:01:48 +01:00
writeFunction: async (chunkArg: Buffer, streamtools) => {
2023-11-06 18:14:21 +01:00
if (firstRun) {
firstRun = false;
2023-11-14 10:55:19 +01:00
const fileType = await plugins.fileType.fileTypeFromBuffer(chunkArg);
const decompressionStream = await this.getDecompressionStream(fileType?.mime as TSupportedMime);
2023-11-06 18:14:21 +01:00
const result: IAnalyzedResult = {
fileType,
2023-11-07 04:19:54 +01:00
isArchive: await this.mimeTypeIsArchive(fileType?.mime),
2023-11-06 18:14:21 +01:00
resultStream,
decompressionStream,
};
2023-11-13 22:11:24 +01:00
await streamtools.push(result);
2023-11-06 18:14:21 +01:00
}
2023-11-14 10:55:19 +01:00
await resultStream.backpressuredPush(chunkArg);
return null;
2023-11-06 18:14:21 +01:00
},
finalFunction: async () => {
2023-11-07 04:19:54 +01:00
resultStream.push(null);
return null;
},
2023-11-06 18:14:21 +01:00
});
2023-11-06 18:14:21 +01:00
return analyzerstream;
}
}