gzipper
Version:
CLI for compressing files.
192 lines • 21.4 kB
JavaScript
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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