masnagam/npm-diet

View on GitHub
bin/npm-diet-measure

Summary

Maintainability
Test Coverage
#!/usr/bin/env node

// Copyright 2018 Masayuki Nagamachi <masayuki.nagamachi@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

'use strict';

const program = require('commander');
const { promisify } = require('util');
const EventEmitter = require('events');
const ora = require('ora');
const rimraf = promisify(require('rimraf'));
const streamToString = require('stream-to-string');
const lib = require('../lib');

const HELP = `
  Description:

    This command installs the specified packages temporarily, and then collects
    metrics of each package used for subsequent package size analyzer.  Finally,
    this command formats the analysis results in the JSON format, and outputs it
    to STDOUT.

    This command supports all package specifier syntax that \`npm\` supports.

  Removing packages:

    This command supports a special package specifier prefix '_'.

    The following command replaces 'del' with 'rimraf', and then makes an
    analysis for the case of installing 'npm-run-all' and 'rimraf':

      $ echo '["npm-run-all","del"]' | npm-diet measure --stdin rimraf _del

    A package specifier prefixed with '_' is removed from a list which contains
    preceding package specifiers.  That means the following two commands don't
    make the same analysis:

      $ npm-diet measure aaa bbb _bbb
      $ npm-diet measure aaa _bbb bbb

    The former makes an analysis for the case of installing only 'aaa'.  On the
    other hand, the latter makes an analysis for the case of installing 'aaa'
    and 'bbb'.

    The version specifier part of the package specifier suffixed with '_' has no
    effect.  So, the following two commands make the same analysis:

      $ npm-diet measure aaa bbb _bbb
      $ npm-diet measure aaa bbb _bbb@^1.1.0
`;

program
  .description(
    'Collect metrics of each installed package')
  .option(
    '--stdin',
    'read package specifiers from STDIN before reading from arguments')
  .arguments(
    '[specs...]')
  .allowUnknownOption()  // for '--no-color'
  .on('--help', () => console.log(HELP))
  .action(async (specs, options) => {
    if (options.stdin) {
      specs = JSON.parse(await streamToString(process.stdin)).concat(specs);
    }

    const spinner = ora();
    const emitter = new EventEmitter();
    emitter.on('prepare', () => {
      spinner.start('Preparing a working dir for installing in temporal...');
    });
    emitter.on('install', (args) => {
      spinner.start(`Installing ${args.join(' ')}...`);
    });
    emitter.on('analyze', () => {
      spinner.start('Analyzing packages...');
    });
    emitter.on('done', () => {
      spinner.stop();
    });

    const workdir = await lib.cli.utils.makeWorkDir();
    try {
      const analysis = await lib.analyze.measure(specs, workdir, emitter);
      console.log(JSON.stringify(analysis));
    } catch (error) {
      spinner.fail(error);
    } finally {
      await rimraf(workdir);
    }
  })
  .parse(process.argv);