UNPKG

@obsidize/tar-browserify

Version:

Browser-based tar utility for packing and unpacking tar files (stream-capable)

113 lines (112 loc) 4.39 kB
import { Constants } from '../common/constants'; import { TarUtility } from '../common/tar-utility'; import { UstarHeaderLinkIndicatorType } from '../header/ustar/ustar-header-link-indicator-type'; import { ArchiveEntry } from './archive-entry'; /** * Generic utility for building a tar octet stream by adding JSON-style entries. * See the `add***()` options in this class definition for details. */ export class ArchiveWriter { constructor(entries = []) { this.entries = entries; } /** * Combines the given array of entries into a single, complete tarball buffer */ static serialize(entries) { let outputLength = Constants.TERMINAL_PADDING_SIZE; const outputBuffers = []; for (const entry of entries) { const entryBytes = entry.toUint8Array(); outputBuffers.push(entryBytes); outputLength += entryBytes.byteLength; } const output = new Uint8Array(outputLength); let offset = 0; for (const entryBuf of outputBuffers) { output.set(entryBuf, offset); offset += entryBuf.byteLength; } return output; } /** * @returns a complete tar buffer from all the currently set tar entries in this instance. */ toUint8Array() { return ArchiveWriter.serialize(this.entries); } /** * Convenience for appending a new entry to the existing `entries` array * @returns `this` for operation chaining */ addEntry(entry) { this.entries.push(entry); return this; } /** * Convenience for appending a new entry to the existing `entries` array. * @returns `this` for operation chaining */ addEntryWith(header, content) { return this.addEntry(new ArchiveEntry({ headerAttributes: header, content })); } /** * Convenience option for building tarball data * @param path - the file name, e.g. './relative/path/to/your/file.txt' * @param content - the content of the file (shocker!) * @param headerOptions - custom options for this entry * @returns `this` for operation chaining */ addTextFile(path, content, headerOptions) { return this.addBinaryFile(path, TarUtility.encodeString(content), headerOptions); } /** * Convenience option for building tarball data * @param path - the file name, e.g. './relative/path/to/your/file.bin' * @param content - the content of the file (shocker!) * @param headerOptions - custom options for this entry * @returns `this` for operation chaining */ addBinaryFile(path, content, headerOptions = {}) { const combinedHeaderOptions = Object.assign({ fileName: path, fileSize: content.byteLength, typeFlag: UstarHeaderLinkIndicatorType.NORMAL_FILE, }, headerOptions); return this.addEntryWith(combinedHeaderOptions, content); } /** * Convenience option for building tarball data * @param path - the directory name, e.g. './relative/path/to/your/dir' * @param headerOptions - custom options for this entry * @returns `this` for operation chaining */ addDirectory(path, headerOptions = {}) { const combinedHeaderOptions = Object.assign({ fileName: path, typeFlag: UstarHeaderLinkIndicatorType.DIRECTORY, }, headerOptions); return this.addEntryWith(combinedHeaderOptions); } /** * Removes any entries from this writer's cache that meet the given predicate condition. * @param predicate - delegate that will return true for any entry that should be removed. * @returns `this` for operation chaining */ removeEntriesWhere(predicate) { this.entries = this.entries.filter((v) => !predicate(v)); return this; } /** * Convenience option for cleaning the header of each listed entry. * When headers are "cleaned", unknown PAX properties will be removed * (e.g. unwanted MacOS "quarantine" headers), and USTAR fields * will be normalized (if necessary). */ cleanAllHeaders() { for (const entry of this.entries) { entry.header.clean(); } return this; } }