import {createReadStream, createWriteStream, stat} from 'fs'; import {pipeline} from 'stream'; import zlib from 'zlib'; import headers from './headers.js'; const { BROTLI_MAX_QUALITY, BROTLI_MODE_GENERIC, BROTLI_MODE_FONT, BROTLI_MODE_TEXT, BROTLI_PARAM_MODE, BROTLI_PARAM_QUALITY, BROTLI_PARAM_SIZE_HINT, Z_BEST_COMPRESSION } = zlib.constants; const { createBrotliCompress, createDeflate, createGzip } = zlib; const zlibDefaultOptions = { level: Z_BEST_COMPRESSION }; const br = (source, mode) => new Promise((res, rej) => { const dest = source + '.br'; stat(source, (err, stats) => { /* istanbul ignore next */ if (err) rej(err); else pipeline( createReadStream(source), createBrotliCompress({ [BROTLI_PARAM_SIZE_HINT]: stats.size, [BROTLI_PARAM_QUALITY]: BROTLI_MAX_QUALITY, [BROTLI_PARAM_MODE]: mode == 'text' ? BROTLI_MODE_TEXT : ( mode === 'font' ? BROTLI_MODE_FONT : /* istanbul ignore next */ BROTLI_MODE_GENERIC ) }), createWriteStream(dest), err => { /* istanbul ignore next */ if (err) rej(err); else res(dest); } ); }); }); const deflate = source => new Promise((res, rej) => { const dest = source + '.deflate'; pipeline( createReadStream(source), createDeflate(zlibDefaultOptions), createWriteStream(dest), err => { /* istanbul ignore next */ if (err) rej(err); else res(dest); } ); }); const gzip = source => new Promise((res, rej) => { const dest = source + '.gzip'; pipeline( createReadStream(source), createGzip(zlibDefaultOptions), createWriteStream(dest), err => { /* istanbul ignore next */ if (err) rej(err); else res(dest); } ); }); export default (source, dest, mode, options) => Promise.all([ br(dest, mode), gzip(dest), deflate(dest) ]).then(([br, gzip, deflate]) => Promise.all([ headers(source, dest, options.headers), headers(source, br, { ...options.headers, 'Content-Encoding': 'br' }), headers(source, gzip, { ...options.headers, 'Content-Encoding': 'gzip' }), headers(source, deflate, { ...options.headers, 'Content-Encoding': 'deflate' }) ]));