UNPKG

gzipper

Version:

CLI for compressing files.

192 lines 21.4 kB
import { Command } from 'commander'; import { Compress } from './Compress.js'; import { getVersion, getLogColor, readableSize } from './helpers.js'; import { Incremental } from './Incremental.js'; import { Config } from './Config.js'; import { Logger } from './logger/Logger.js'; import { LogLevel } from './logger/LogLevel.enum.js'; export class Index { commander = new Command(); logger = new Logger(); argv = process.argv; env = process.env; async exec() { this.commander.version(getVersion()).name('gzipper'); this.commander .command('compress <path> [outputPath]') .alias('c') .description('compress selected path and optionally set output directory') .option('-v, --verbose', 'detailed level of logs') .option('--incremental', 'incremental compression') .option('-e, --exclude <extensions>', 'exclude file extensions from compression, example: jpeg,jpg...', this.optionToArray.bind(this)) .option('-i, --include <extensions>', 'include file extensions for compression, example: js,css,html...', this.optionToArray.bind(this)) .option('-t, --threshold <number>', 'exclude assets smaller than this byte size. 0 (default)', (value) => parseInt(value)) .option('--deflate', 'enable deflate compression') .option('--brotli', 'enable brotli compression') .option('--gzip', 'enable gzip compression') .option('--zopfli', 'enable zopfli compression') .option('--zstd', 'enable zstd compression') .option('--gzip-level <number>', 'gzip compression level 6 (default), 0 (no compression) - 9 (best compression)', (value) => parseInt(value)) .option('--gzip-memory-level <number>', 'amount of memory which will be allocated for gzip compression 8 (default), 1 (minimum memory) - 9 (maximum memory)', (value) => parseInt(value)) .option('--gzip-strategy <number>', 'gzip compression strategy 0 (default), 1 (filtered), 2 (huffman only), 3 (RLE), 4 (fixed)', (value) => parseInt(value)) .option('--deflate-level <number>', 'deflate compression level 6 (default), 0 (no compression) - 9 (best compression)', (value) => parseInt(value)) .option('--deflate-memory-level <number>', 'amount of memory which will be allocated for deflate compression 8 (default), 1 (minimum memory) - 9 (maximum memory)', (value) => parseInt(value)) .option('--deflate-strategy <number>', 'deflate compression strategy 0 (default), 1 (filtered), 2 (huffman only), 3 (RLE), 4 (fixed)', (value) => parseInt(value)) .option('--brotli-param-mode <value>', 'default, text (for UTF-8 text), font (for WOFF 2.0 fonts)') .option('--brotli-quality <number>', 'brotli compression quality 11 (default), 0 - 11', (value) => parseInt(value)) .option('--brotli-size-hint <number>', 'expected input size 0 (default)', (value) => parseInt(value)) .option('--zopfli-num-iterations <number>', 'maximum amount of times to rerun forward and backward pass to optimize LZ77 compression cost', (value) => parseInt(value)) .option('--zopfli-block-splitting', 'splits the data in multiple deflate blocks with optimal choice for the block boundaries') .option('--zopfli-block-splitting-max <number>', 'maximum amount of blocks to split into (0 for unlimited, but this can give extreme results that hurt compression on some files)', (value) => parseInt(value)) .option('--zstd-level <number>', 'zstd compression level 1 (default), 5 (best compression)', (value) => parseInt(value)) .option('--output-file-format <value>', 'output file format with default artifacts [filename].[ext].[compressExt]') .option('--remove-larger', 'remove compressed files if they larger than uncompressed originals') .option('--skip-compressed', 'skip compressed files if they already exist') .option('--workers <number>', 'numbers of workers which will be spawned, system CPU cores count (default)', (value) => parseInt(value)) .option('--no-color', 'disable logger colorful messages') .action(this.compress.bind(this)); const cache = this.commander .command('cache') .description('manipulations with cache'); cache .command('purge') .description('purge cache storage') .action(this.cachePurge.bind(this)); cache .command('size') .description('size of cached resources') .action(this.cacheSize.bind(this)); await this.commander.parseAsync(this.argv); } async compress(target, outputPath, options) { const adjustedOptions = { verbose: this.env.GZIPPER_VERBOSE ? !!parseInt(this.env.GZIPPER_VERBOSE) : options.verbose, incremental: this.env.GZIPPER_INCREMENTAL ? !!parseInt(this.env.GZIPPER_INCREMENTAL) : options.incremental, exclude: this.optionToArray(this.env.GZIPPER_EXCLUDE) || options.exclude, include: this.optionToArray(this.env.GZIPPER_INCLUDE) || options.include, threshold: parseInt(this.env.GZIPPER_THRESHOLD) || options.threshold || 0, brotli: this.env.GZIPPER_BROTLI ? !!parseInt(this.env.GZIPPER_BROTLI) : options.brotli, deflate: this.env.GZIPPER_DEFLATE ? !!parseInt(this.env.GZIPPER_DEFLATE) : options.deflate, gzip: this.env.GZIPPER_GZIP ? !!parseInt(this.env.GZIPPER_GZIP) : options.gzip, zopfli: this.env.GZIPPER_ZOPFLI ? !!parseInt(this.env.GZIPPER_ZOPFLI) : options.zopfli, zstd: this.env.GZIPPER_ZSTD ? !!parseInt(this.env.GZIPPER_ZSTD) : options.zstd, gzipLevel: parseInt(this.env.GZIPPER_GZIP_LEVEL) || options.gzipLevel, gzipMemoryLevel: parseInt(this.env.GZIPPER_GZIP_MEMORY_LEVEL) || options.gzipMemoryLevel, gzipStrategy: parseInt(this.env.GZIPPER_GZIP_STRATEGY) || options.gzipStrategy, deflateLevel: parseInt(this.env.GZIPPER_DEFLATE_LEVEL) || options.deflateLevel, deflateMemoryLevel: parseInt(this.env.GZIPPER_DEFLATE_MEMORY_LEVEL) || options.deflateMemoryLevel, deflateStrategy: parseInt(this.env.GZIPPER_DEFLATE_STRATEGY) || options.deflateStrategy, brotliParamMode: this.env.GZIPPER_BROTLI_PARAM_MODE || options.brotliParamMode, brotliQuality: parseInt(this.env.GZIPPER_BROTLI_QUALITY) || options.brotliQuality, brotliSizeHint: parseInt(this.env.GZIPPER_BROTLI_SIZE_HINT) || options.brotliSizeHint, zopfliNumIterations: parseInt(this.env.GZIPPER_ZOPFLI_NUM_ITERATIONS) || options.zopfliNumIterations, zopfliBlockSplitting: this.env.GZIPPER_ZOPFLI_BLOCK_SPLITTING ? !!parseInt(this.env.GZIPPER_ZOPFLI_BLOCK_SPLITTING) : options.zopfliBlockSplitting, zopfliBlockSplittingMax: parseInt(this.env.GZIPPER_ZOPFLI_BLOCK_SPLITTING_MAX) || options.zopfliBlockSplittingMax, zstdLevel: parseInt(this.env.GZIPPER_ZSTD_LEVEL) || options.zstdLevel, outputFileFormat: this.env.GZIPPER_OUTPUT_FILE_FORMAT || options.outputFileFormat, removeLarger: this.env.GZIPPER_REMOVE_LARGER ? !!parseInt(this.env.GZIPPER_REMOVE_LARGER) : options.removeLarger, skipCompressed: this.env.GZIPPER_SKIP_COMPRESSED ? !!parseInt(this.env.GZIPPER_SKIP_COMPRESSED) : options.skipCompressed, workers: parseInt(this.env.GZIPPER_WORKERS) || options.workers, color: getLogColor(options.color, this.env), }; await this.runCompress(target, outputPath, adjustedOptions); } async cachePurge() { this.logger.initialize({ verbose: true, }); const config = new Config(); const incremental = new Incremental(config); try { await incremental.cachePurge(); this.logger.log('Cache has been purged, you are free to initialize a new one.', LogLevel.SUCCESS); } catch (err) { this.logger.log(err, LogLevel.ERROR); } } async cacheSize() { this.logger.initialize({ verbose: true, }); const incremental = new Incremental(); try { const size = await incremental.cacheSize(); this.logger.log(size ? `Cache size is ${readableSize(size)}` : `Cache is empty, initialize a new one with --incremental option.`, LogLevel.INFO); } catch (err) { this.logger.log(err, LogLevel.ERROR); } } async runCompress(target, outputPath, options) { this.logger.initialize({ verbose: options.verbose, }); const compress = new Compress(target, outputPath, this.filterOptions(options)); try { await compress.run(); } catch (err) { this.logger.log(err, LogLevel.ERROR); } } // Delete undefined and NaN options. filterOptions(options) { return Object.keys(options) .filter((key) => { return (Object.prototype.hasOwnProperty.call(options, key) && !(options[key] === undefined || options[key] !== options[key])); }) .reduce((obj, key) => ({ ...obj, [key]: options[key], }), {}); } optionToArray(value) { if (typeof value === 'string' && value) { return value.split(',').map((item) => item.trim()); } return value; } } if (process.env.NODE_ENV !== 'test') { new Index().exec(); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmluLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2Jpbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBRXBDLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDekMsT0FBTyxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsWUFBWSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBRXJFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUMvQyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3JDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFFckQsTUFBTSxPQUFPLEtBQUs7SUFDUixTQUFTLEdBQUcsSUFBSSxPQUFPLEVBQUUsQ0FBQztJQUNsQyxNQUFNLEdBQUcsSUFBSSxNQUFNLEVBQUUsQ0FBQztJQUN0QixJQUFJLEdBQWEsT0FBTyxDQUFDLElBQUksQ0FBQztJQUM5QixHQUFHLEdBQXNCLE9BQU8sQ0FBQyxHQUFHLENBQUM7SUFFckMsS0FBSyxDQUFDLElBQUk7UUFDUixJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUVyRCxJQUFJLENBQUMsU0FBUzthQUNYLE9BQU8sQ0FBQyw4QkFBOEIsQ0FBQzthQUN2QyxLQUFLLENBQUMsR0FBRyxDQUFDO2FBQ1YsV0FBVyxDQUFDLDREQUE0RCxDQUFDO2FBQ3pFLE1BQU0sQ0FBQyxlQUFlLEVBQUUsd0JBQXdCLENBQUM7YUFDakQsTUFBTSxDQUFDLGVBQWUsRUFBRSx5QkFBeUIsQ0FBQzthQUNsRCxNQUFNLENBQ0wsNEJBQTRCLEVBQzVCLGdFQUFnRSxFQUNoRSxJQUFJ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