UNPKG

r2-utils-js

Version:

Readium 2 'utils' for NodeJS (TypeScript)

304 lines 11 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const fs = require("fs"); const path = require("path"); const StreamZip = require("node-stream-zip"); const yauzl = require("yauzl"); const unzipper = require("unzipper"); console.log("process.cwd():"); console.log(process.cwd()); console.log("__dirname:"); console.log(__dirname); const args = process.argv.slice(2); console.log("args:"); console.log(args); if (!args[0]) { console.log("FILEPATH ARGUMENT IS MISSING."); process.exit(1); } const argPath = args[0].trim(); let filePath = argPath; console.log(filePath); if (!fs.existsSync(filePath)) { filePath = path.join(__dirname, argPath); console.log(filePath); if (!fs.existsSync(filePath)) { filePath = path.join(process.cwd(), argPath); console.log(filePath); if (!fs.existsSync(filePath)) { console.log("FILEPATH DOES NOT EXIST."); process.exit(1); } } } const stats = fs.lstatSync(filePath); if (!stats.isFile() && !stats.isDirectory()) { console.log("FILEPATH MUST BE FILE OR DIRECTORY."); process.exit(1); } const fileName = path.basename(filePath); const ext = path.extname(fileName); const VERBOSE = process.env.DEBUG || false; const argIterations = args[1] ? args[1].trim() : undefined; const N_ITERATIONS = argIterations ? parseInt(argIterations, 10) : 5; const argExtra = args[2] ? args[2].trim() : undefined; const CHECK_ONLY_ZIP3 = argExtra === "1"; const zip1 = (file) => tslib_1.__awaiter(void 0, void 0, void 0, function* () { return new Promise((resolve, reject) => { const zip = new StreamZip({ file, storeEntries: true, }); zip.on("error", (err) => { console.log("--ZIP error: " + filePath); console.log(err); reject(err); }); zip.on("entry", (_entry) => { }); zip.on("extract", (entry, f) => { console.log("--ZIP extract:"); console.log(entry.name); console.log(f); }); zip.on("ready", () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { const zipEntries = Object.values(zip.entries()); if (VERBOSE) { process.stdout.write("## 1 ##\n"); } for (const zipEntry of zipEntries) { if (zipEntry.isDirectory) { continue; } const promize = new Promise((res, rej) => { zip.stream(zipEntry.name, (err, stream) => tslib_1.__awaiter(void 0, void 0, void 0, function* () { if (err) { console.log(err); rej(err); return; } const totalBytes = streamReadAll(stream); process.nextTick(() => { res(totalBytes); }); })); }); const size = yield promize; if (zipEntry.size !== size) { console.log(`1 SIZE MISMATCH? ${zipEntry.name} ${zipEntry.size} != ${size}`); } if (VERBOSE) { process.stdout.write(` ${zipEntry.name} `); } else { process.stdout.write("."); } } process.stdout.write("\n"); process.nextTick(() => { zip.close(); process.nextTick(() => { resolve(); }); }); })); }); }); zip1.zipName = "node-stream-zip"; const zip2 = (file) => tslib_1.__awaiter(void 0, void 0, void 0, function* () { return new Promise((resolve, reject) => { yauzl.open(file, { lazyEntries: true, autoClose: false }, (error, zip) => { if (error || !zip) { console.log("yauzl init ERROR"); console.log(error); reject(error); return; } zip.on("error", (erro) => { console.log("yauzl ERROR"); console.log(erro); reject(erro); }); if (VERBOSE) { process.stdout.write("## 2 ##\n"); } zip.readEntry(); zip.on("entry", (zipEntry) => tslib_1.__awaiter(void 0, void 0, void 0, function* () { if (zipEntry.fileName[zipEntry.fileName.length - 1] === "/") { } else { const promize = new Promise((res, rej) => { zip.openReadStream(zipEntry, (err, stream) => { if (err || !stream) { console.log(err); rej(err); return; } const totalBytes = streamReadAll(stream); process.nextTick(() => { res(totalBytes); }); }); }); const size = yield promize; if (zipEntry.uncompressedSize !== size) { console.log(`2 SIZE MISMATCH? ${zipEntry.fileName} ${zipEntry.uncompressedSize} != ${size}`); } if (VERBOSE) { process.stdout.write(` ${zipEntry.fileName} `); } else { process.stdout.write("."); } } zip.readEntry(); })); zip.on("end", () => { process.stdout.write("\n"); process.nextTick(() => { zip.close(); process.nextTick(() => { resolve(); }); }); }); zip.on("close", () => { }); }); }); }); zip2.zipName = "yauzl"; const zip3 = (file) => tslib_1.__awaiter(void 0, void 0, void 0, function* () { return new Promise((resolve, reject) => tslib_1.__awaiter(void 0, void 0, void 0, function* () { let zip; try { zip = yield unzipper.Open.file(file); } catch (err) { console.log(err); reject(err); return; } if (VERBOSE) { process.stdout.write("## 3 ##\n"); } for (const zipEntry of zip.files) { if (zipEntry.type === "Directory") { continue; } const stream = zipEntry.stream(); stream.on("error", (err) => { console.log("err1"); console.log(err); }); const promize = streamReadAll(stream); let size; try { size = yield promize; } catch (err) { console.log("err2"); console.log(err); reject(err); return; } if (zipEntry.uncompressedSize !== size) { console.log(`3 SIZE MISMATCH? ${zipEntry.path} ${zipEntry.uncompressedSize} != ${size}`); } if (VERBOSE) { process.stdout.write(` ${zipEntry.path} `); } else { process.stdout.write("."); } } process.stdout.write("\n"); resolve(); })); }); zip3.zipName = "unzipper"; const zips = CHECK_ONLY_ZIP3 ? [zip3] : [zip1, zip2, zip3]; function processFile(file) { return tslib_1.__awaiter(this, void 0, void 0, function* () { console.log("-------------------------------"); console.log(`${file}`); console.log("-------------------------------"); let winner = 0; let minNanoOverall = Number.MAX_SAFE_INTEGER; let iZip = 0; for (const zip of zips) { iZip++; if (VERBOSE) { console.log("-------------------------------"); } for (let i = 0; i < N_ITERATIONS; i++) { process.stdout.write(`${i + 1}/${N_ITERATIONS} `); const time = process.hrtime(); yield zip(file); const diffTime = process.hrtime(time); const nanos = diffTime[0] * 1e9 + diffTime[1]; zip.minNano = nanos; if (nanos < minNanoOverall) { minNanoOverall = nanos; winner = iZip; } if (VERBOSE) { console.log(`Zip ${iZip}: ${diffTime[0]} seconds + ${diffTime[1]} nanoseconds`); } } } if (VERBOSE) { console.log("-------------------------------"); } iZip = 0; for (const zip of zips) { iZip++; const won = iZip === winner; console.log(`${won ? ">>" : "--"} Zip ${iZip} (${zip.zipName}) => ${zip.minNano.toLocaleString()} nanoseconds ${won ? " [ WINNER ]" : `[ +${(zip.minNano - minNanoOverall).toLocaleString()} ]`}`); } }); } if (stats.isDirectory()) { (() => tslib_1.__awaiter(void 0, void 0, void 0, function* () { const files = fs.readdirSync(filePath, { withFileTypes: true }). filter((f) => f.isFile() && /((\.epub3?)|(\.zip)|(\.cbz))$/i.test(f.name)). map((f) => path.join(filePath, f.name)); for (const file of files) { yield processFile(file); } }))(); } else if (/((\.epub3?)|(\.zip)|(\.cbz))$/i.test(ext)) { (() => tslib_1.__awaiter(void 0, void 0, void 0, function* () { yield processFile(filePath); }))(); } function streamReadAll(readStream) { return tslib_1.__awaiter(this, void 0, void 0, function* () { return new Promise((resolve, reject) => { let totalBytes = 0; const cleanup = () => { readStream.removeListener("data", handleData); readStream.removeListener("error", handleError); readStream.removeListener("end", handleEnd); }; const handleError = (err) => { cleanup(); reject(err); }; readStream.on("error", handleError); const handleData = (data) => { totalBytes += data.length; }; readStream.on("data", handleData); const handleEnd = () => { cleanup(); resolve(totalBytes); }; readStream.on("end", handleEnd); }); }); } //# sourceMappingURL=perf-zip-cli.js.map