import fs from 'fs'; import path from 'path'; import archiver from 'archiver'; import crypto from 'crypto'; const BASE64_KEYS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; const HEXCHAR = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'] var BASE64_VALUES = new Array(123); for (let i = 0; i < 123; ++i) BASE64_VALUES[i] = 64; for (let i = 0; i < 64; ++i) BASE64_VALUES[BASE64_KEYS.charCodeAt(i)] = i; var _t = ['', '', '', '']; var uuidTemplate = _t.concat(_t, '-', _t, '-', _t, '-', _t, '-', _t, _t, _t); var indices = uuidTemplate.map(function (value: string, index: number) { return value === '-' ? NaN : index; }).filter(isFinite); export class Utils { private static logLevel: Utils.LogLevel = 1; public static mkdir(dir: string): void { if (!fs.existsSync(dir)) { let parentDir = path.dirname(dir); this.mkdir(parentDir); fs.mkdirSync(dir); } } public static rmdir(dir: string): void { if (!fs.existsSync(dir)) return; let files = fs.readdirSync(dir); for (let item of files) { let itemPath = path.join(dir, item); let stat = fs.statSync(itemPath); stat.isDirectory() ? this.rmdir(itemPath) : fs.unlinkSync(itemPath); } fs.rmdirSync(dir); } public static zipdir(srcDir: string, outputFile: string): Promise { Utils.mkdir(path.dirname(outputFile)); var promise: Promise = new Promise((resolve: () => void, reject: (reason?: any) => void) => { let writeStream = fs.createWriteStream(outputFile); let archive = archiver('zip', { // encoding: 'utf-8', // forceZip64: true, zlib: { level: 9 } }); writeStream.on('close', () => { resolve(); }); archive.on('error', function (error: archiver.ArchiverError) { reject(error) }) archive.pipe(writeStream); archive.directory(srcDir, false); archive.finalize(); }); return promise; } public static md5dir(dir: string, md5?: Utils.FileMD5[]): Utils.FileMD5[] { md5 = md5 || []; let files = fs.readdirSync(dir); for (let file of files) { let filePath = path.join(dir, file); let stat = fs.statSync(filePath); if (stat.isDirectory()) { this.md5dir(filePath, md5) } else { let buffer = fs.readFileSync(filePath); let hash = crypto.createHash('md5'); hash.update(buffer); let hex = hash.digest('hex'); md5.push({ path: filePath, md5: hex }); } } return md5; } public static fileMD5Compare(src: Utils.FileMD5[], dst: Utils.FileMD5[]): Utils.FileMD5CompareResult { let result: Utils.FileMD5CompareResult = { added: [], deleted: [], changed: [], same: [] }; let srcCopy = src.concat([]); let dstCopy = dst.concat([]); let dstItem: Utils.FileMD5 | undefined; while (dstItem = dstCopy.shift()) { let foundItem: Utils.FileMD5 | undefined = undefined; for (let j = 0, srcLenght = srcCopy.length; j < srcLenght; j++) { let srcItem = srcCopy[j]; if (srcItem.path === dstItem.path) { foundItem = srcItem; srcCopy.splice(j, 1); break; } } if (!foundItem) { result.added.push(dstItem); } else { foundItem.md5 === dstItem.md5 ? result.same.push(dstItem) : result.changed.push(dstItem) } } result.deleted.push(...srcCopy); return result; } public static setLogLevel(level: Utils.LogLevel): void { Utils.logLevel = level; } public static log(text: string, level: Utils.LogLevel.Simple | Utils.LogLevel.Particular = Utils.LogLevel.Simple): void { if (Utils.logLevel === Utils.LogLevel.Disable) return; if (level <= Utils.logLevel) { console.log(text); } } public static toBase64(uuid: string) { let j = 2; let base64 = uuid.substring(0, j) for (let i = 2; i < 22; i += 2) { let hex1 = HEXCHAR.indexOf(uuid.charAt(indices[j++])); let hex2 = HEXCHAR.indexOf(uuid.charAt(indices[j++])); let hex3 = HEXCHAR.indexOf(uuid.charAt(indices[j++])); let lhs = (hex1 << 2) | (hex2 >> 2); let rhs = ((hex2 & 3) << 4) | hex3; base64 += BASE64_KEYS.charAt(lhs); base64 += BASE64_KEYS.charAt(rhs); } return base64; } public static toUUID(base64: string) { let baselen = base64.length; if (baselen < 22) { return base64; } uuidTemplate[0] = base64[0]; uuidTemplate[1] = base64[1]; for (let i = 2, j = 2; i < 22; i += 2) { let lhs = BASE64_VALUES[base64.charCodeAt(i)]; let rhs = BASE64_VALUES[base64.charCodeAt(i + 1)]; uuidTemplate[indices[j++]] = HEXCHAR[lhs >> 2]; uuidTemplate[indices[j++]] = HEXCHAR[((lhs & 3) << 2) | rhs >> 4]; uuidTemplate[indices[j++]] = HEXCHAR[rhs & 0xF]; } return uuidTemplate.join(''); } } export namespace Utils { export type FileMD5 = { path: string, md5: string }; export type FileMD5CompareResult = { added: FileMD5[], deleted: FileMD5[], changed: FileMD5[], same: FileMD5[] } export enum LogLevel { Disable = 0, Simple = 1, Particular = 2 }; }