Files
smartarchive/ts_shared/classes.tartools.ts

90 lines
2.7 KiB
TypeScript
Raw Normal View History

import * as plugins from './plugins.js';
import type { IArchiveEntry, ITarEntry, TCompressionLevel } from './interfaces.js';
import { GzipTools } from './classes.gziptools.js';
/**
* TAR archive creation and extraction utilities using modern-tar (browser-compatible)
*/
export class TarTools {
/**
* Pack files into a TAR buffer
*/
public async packFiles(files: IArchiveEntry[]): Promise<Uint8Array> {
const entries: ITarEntry[] = [];
for (const file of files) {
let data: Uint8Array;
if (typeof file.content === 'string') {
data = new TextEncoder().encode(file.content);
} else if (file.content instanceof Uint8Array) {
data = file.content;
} else if (file.content instanceof plugins.smartfile.SmartFile) {
data = new Uint8Array(file.content.contents);
} else if (file.content instanceof plugins.smartfile.StreamFile) {
const buffer = await file.content.getContentAsBuffer();
data = new Uint8Array(buffer);
} else {
throw new Error('Unsupported content type for TAR entry');
}
entries.push({
header: {
name: file.archivePath,
size: data.length,
type: 'file',
mode: file.mode,
mtime: file.mtime,
},
body: data,
});
}
return plugins.modernTar.packTar(entries);
}
/**
* Extract a TAR buffer to an array of entries
*/
public async extractTar(data: Uint8Array): Promise<Array<{ path: string; content: Uint8Array; isDirectory: boolean }>> {
const entries = await plugins.modernTar.unpackTar(data);
const result: Array<{ path: string; content: Uint8Array; isDirectory: boolean }> = [];
for (const entry of entries) {
const isDirectory = entry.header.type === 'directory' || entry.header.name.endsWith('/');
// modern-tar uses 'data' property, not 'body'
const content = entry.data ?? new Uint8Array(0);
result.push({
path: entry.header.name,
content,
isDirectory,
});
}
return result;
}
/**
* Pack files into a TAR.GZ buffer
*/
public async packFilesToTarGz(
files: IArchiveEntry[],
compressionLevel?: TCompressionLevel
): Promise<Uint8Array> {
const tarBuffer = await this.packFiles(files);
const gzipTools = new GzipTools();
return gzipTools.compress(tarBuffer, compressionLevel);
}
/**
* Extract a TAR.GZ buffer to an array of entries
*/
public async extractTarGz(data: Uint8Array): Promise<Array<{ path: string; content: Uint8Array; isDirectory: boolean }>> {
const gzipTools = new GzipTools();
const tarBuffer = await gzipTools.decompress(data);
return this.extractTar(tarBuffer);
}
}