0.1.6•Updated a month ago
import { BlobWriter, Uint8ArrayReader, Uint8ArrayWriter, ZipWriter, ZipReader, BlobReader } from "https://deno.land/x/zipjs@v2.7.57/index.js";
import { existsSync } from "jsr:@std/fs";
import { join, relative } from "jsr:@std/path";
interface ZipOptions {
destination_file_path?: string
}
export interface I_File {
actual_path: string
path_in_zip: string
}
export class Zip {
private files: I_File[]
private destination_file_path?: string
private _blob!: Blob;
private _length: number = 0;
private constructor(files: I_File[], { destination_file_path }: ZipOptions = {}) {
this.files = files;
this.destination_file_path = destination_file_path;
}
private async getZipFileBlob() {
const zipWriter = new ZipWriter(new BlobWriter('application/zip'));
await Promise.all(this.files.map(file => {
zipWriter.add(file.path_in_zip, new Uint8ArrayReader(Deno.readFileSync(file.actual_path)));
}))
return zipWriter.close();
}
async process() {
this._blob = await this.getZipFileBlob();
return this;
}
get length() {
return this.blob?.size ?? 0;
}
get blob() {
return this._blob;
}
async save() {
if(!this.destination_file_path) throw new Error('No destination file path provided!');
Deno.writeFileSync(this.destination_file_path, await this.blob.bytes());
}
get stream() {
return this.blob.stream();
}
static Process(files: I_File[], options?: ZipOptions) {
return new Zip(files, options).process();
}
static async Unzip(body: ReadableStream<Uint8Array<ArrayBufferLike>> | Blob, root_path: string) {
const path = this.EnsurePathExists(root_path);
let reader;
if(body instanceof Blob) {
reader = new ZipReader(new BlobReader(body));
} else {
reader = new ZipReader(body);
}
for(const entry of (await reader.getEntries())) {
const entry_path_depths = entry.filename.split(/[\\\/]+/g);
const entry_file_name = entry_path_depths.pop()!;
const entry_path_full = join(path, entry_path_depths.join('/'));
const entry_dir = this.EnsurePathExists(entry_path_full, path);
const data = await entry.getData?.(new Uint8ArrayWriter());
if(data) Deno.writeFileSync(join(entry_dir, entry_file_name), data);
};
return true;
}
private static EnsurePathExists(target_path: string, start_path?: string) {
start_path ||= Deno.cwd();
const directory_depths = relative(start_path, target_path).split(/[\\\/]+/g);
let current_path = start_path;
while(directory_depths.length) {
const next_dir = join(current_path, directory_depths.shift()!);
if(!existsSync(next_dir, { isDirectory: true })) {
Deno.mkdirSync(next_dir);
}
current_path = next_dir;
}
return current_path;
}
}