All files index.ts

23.91% Statements 11/46
8.82% Branches 3/34
0% Functions 0/5
25% Lines 11/44

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85    1x 1x 1x 1x 1x 1x 1x                       1x   1x   1x   1x                                                                                                                    
 
 
const glob = require('glob');
const bytes = require('bytes');
const fs = require('fs');
const { cosmiconfig } = require('cosmiconfig');
const { program } = require('commander');
const message = require('./message');
const sizes = require('./sizes');
 
type fileType = {
  path: string;
  maxSize?: number;
  minSize?: number;
  compression?: string;
  warnOnly?: boolean;
  externals?: { [key: string]: string };
};
type groupFilesType = fileType[];
 
program.option('-c, --config <config>', 'path containing file size config setup').parse(process.argv);
 
const explorer = cosmiconfig('buildsizes', ['.buildsizes.json', '.buildsizes.js', 'buildsizes.config.js']);
 
const configPath = program?.config;
 
module.exports = explorer
  .search(configPath)
  .then((result: { config: { failMessage: string; files: groupFilesType } }) => {
    const { config } = result;
    const { files, failMessage } = config;
    const hasError = [];
    files.map((file: fileType) => {
      const paths = glob.sync(file.path);
      if (!paths.length) {
        return message('exit', `Sorry, there is no matching file for ${file.path} in ${process.cwd()}`);
      }
      return paths.map((path: string) => {
        const { maxSize, minSize, compression, externals } = file;
        const maxFileSize = bytes(maxSize) || Infinity;
        const minFileSize = bytes(minSize) || 0;
        const size = sizes(fs.readFileSync(path, 'utf8'), compression);
 
        // externals subtract from total size
        let externalsTotalSize = 0;
        if (externals) {
          Object.keys(externals).forEach((idx) => {
            externalsTotalSize += bytes(externals[idx]);
          });
        }
        const externalSize = externalsTotalSize > 0 && bytes(size - externalsTotalSize);
 
        // messages for build size checks
        const maxSizeMsg = `${bytes(maxFileSize)} (${compression}d)`;
        const sizeMsg = `${externalSize || bytes(size)}`;
 
        let minSizeText = '';
        if (minFileSize > 0) minSizeText = `minSize ${bytes(minFileSize)} < `;
 
        const basicMsg = `${path}\n          ${minSizeText || ''}${sizeMsg} < maxSize ${maxSizeMsg}`;
 
        // validate build sizes
        const invalidMaxSize = size - externalsTotalSize > maxFileSize;
        const invalidMinSize = size - externalsTotalSize < minFileSize;
        if (invalidMaxSize || invalidMinSize) {
          if (file.warnOnly) return message('warning', basicMsg);
          hasError.push('');
          return message('failure', basicMsg);
        }
        return message('success', basicMsg);
      });
    });
    if (hasError.length) {
      message(
        'exit',
        `Build size check has failed in ${hasError.length} file${hasError.length > 1 ? 's' : ''}\n${failMessage || ''}`
      );
    } else {
      message('complete', `Build size check have passed, please continue on.`);
    }
  })
  .catch(() => {
    return message('exit', `Sorry, cannot find config file in ${configPath || 'root'} path\n`);
  });