UNPKG

antfarm

Version:

File automation framework for ants.

278 lines (225 loc) 8.45 kB
import {Environment} from "../environment/environment"; import {FileJob} from "./fileJob"; import {Job} from "./job"; import {FolderJob} from "./folderJob"; import {JobProperty} from "./jobProperty"; const tmp = require("tmp"), fs = require("fs"), path = require("path"), JSZip = require("jszip"), _ = require("lodash"), Reflect = require("reflect-metadata"); export class PackedJob extends FileJob { protected e: Environment; protected _job: Job; constructor(e: Environment, job: Job) { // let job_name = job.name; super(e, job.name); let pj = this; pj.e = e; pj.job = job; } protected get job() { return this._job; } protected set job(job: Job) { this._job = job; } /** * Makes job ticket and returns the _path to the temporary file. * @param job * @returns {string} */ protected getJobTicket(job: Job) { let pj = this; // Make job ticket let json = job.getJSON(); let tmpobj = tmp.dirSync(); let dir = tmpobj.name; let file_name = dir + path.sep + "ticket.json"; try { fs.writeFileSync(file_name, json, "utf8"); } catch (err) { pj.e.log(3, `Error writing job ticket to temporary file`, pj); } return file_name; } protected buildZip(zip: any, callback) { // Save out zip let pj = this; let job = this.job; let tmpobj = tmp.dirSync(); let dir = tmpobj.name; let file_name = job.name + ".antpack.zip"; let file_path = dir + path.sep + file_name; zip .generateNodeStream({type: "nodebuffer", streamFiles: true}) .pipe(fs.createWriteStream(file_path)) .on("finish", function () { // JSZip generates a readable stream with a "end" event, // but is piped here in a writable stream which emits a "_finish" event. pj.path = file_path; pj.name = file_name; callback(); }); } /** * Packs the related job on construction. */ public execPack(done) { let pj = this; let job = pj.job; let ticketPath = pj.getJobTicket(job); let zip = new JSZip(); // Add ticket to zip fs.readFile(ticketPath, function(err, data) { if (err) throw err; zip.file("_ticket/ticket.json", data); if (job.isFile()) { fs.readFile(job.path, (err, data) => { if (err) throw err; zip.file("_asset/" + job.name, data); pj.buildZip(zip, () => { done(); }); }); } else if (job.isFolder()) { job.files.forEach(file => { fs.readFile(file.path, function(err, data) { if (err) throw err; zip.file("_asset" + path.sep + job.nameProper + path.sep + file.name, data); pj.buildZip(zip, () => { done(); }); }); }); } else { pj.buildZip(zip, () => { done(); }); } }); } protected restoreJobTicket(jsonTicket) { let pj = this; let jobObject, job; try { jobObject = JSON.parse(jsonTicket); if (jobObject._type === "file") { job = new FileJob(pj.e, jobObject._id); } else if (jobObject._type === "folder") { job = new FolderJob(pj.e, jobObject._id); } else { pj.e.log(3, `Cannot unpack this type of job: ${jobObject._type}`, pj); } } catch (err) { pj.e.log(3, `Unpack ticket parse error: ${err}.`, pj); pj.e.log(3, `Unparsable ticket: ${jsonTicket}.`, pj); } // Restore property values let props = {}; _.each(jobObject._properties, prop => { props[prop._key] = new JobProperty(prop._key, prop._value); }); job.propertyValues = props; // Restore lifecycle job.lifeCycle = jobObject._lifeCycle; return job; } public execUnpack(done) { // console.log("unpacking"); let pj = this; let job = pj.job; // Read the zip to a buffer fs.readFile(job.path, (err, data) => { if (err) { pj.e.log(3, `Unpacking readFile error: ${err}`, pj); } // Open the zip in JSZip JSZip.loadAsync(data).then((zip) => { // Restore job ticket and create job zip.folder("_ticket").forEach((relativePath, file) => { zip.file(`_ticket${path.sep}${relativePath}`).async("string") .then((content) => { // Restore old job ticket job = pj.restoreJobTicket(content); // Restore _files pj.restoreFiles(job, zip, (unpackedJob) => { done(unpackedJob); }); }); }); }); }); } protected restoreFiles(job: Job, zip: any, callback) { let pj = this; // Check for valid pack format if (zip.folder("_asset").length > 1) { pj.e.log(2, `Restored job did not contain any file assets.`, pj, [job]); } if (job.isFolder()) { pj.extractFiles(zip, false, "_asset/", (folderPath, folderName) => { job.path = folderPath; job.rename(folderName); callback(job); }); } else if (job.isFile()) { pj.extractFiles(zip, true, "_asset/", (filePath, fileName) => { job.path = filePath; job.rename(fileName); callback(job); }); } } protected extractFiles(zip: any, single: boolean, zipPath: string, callback: any, totalFiles?: number) { let pj = this; let tmpobj = tmp.dirSync(); let tempPath = tmpobj.name; let fileNumber = 1; if (!totalFiles) { totalFiles = 0; zip.folder(zipPath).forEach((asset) => totalFiles++ ); } if (single === true) { zip.folder(zipPath).forEach((relativePath, asset) => { if (fileNumber > 1) { pj.e.log(3, `More than 1 files found when extracting a file job.`, pj); } else { let newRelPath = zipPath + relativePath; if (asset.dir === "true") { totalFiles--; pj.extractFiles(zip, single, newRelPath, callback, totalFiles); } else { zip.file(newRelPath).async("nodebuffer") .then((content) => { fileNumber++; let filePath = tempPath + path.sep + relativePath; fs.writeFileSync(filePath, content); callback(filePath, relativePath); }); } } }); } else { zip.folder(zipPath).forEach((relativePath, asset) => { let newRelPath = zipPath + relativePath; if (asset.dir === true) { totalFiles--; pj.extractFiles(zip, single, newRelPath, callback, totalFiles); } else { zip.file(newRelPath).async("nodebuffer") .then((content) => { let filePath = tempPath + path.sep + relativePath; fs.writeFileSync(filePath, content); if (totalFiles === fileNumber) { let rootFolderName = newRelPath.split(path.sep)[1]; callback(tempPath, rootFolderName); } fileNumber++; }); } }); } } }