zoukankan      html  css  js  c++  java
  • 一、 common-bin源码

    'use strict';
    
    const debug = require('debug')('common-bin');
    const cp = require('child_process');
    const is = require('is-type-of');
    const unparse = require('dargs');
    
    // 存储子进程
    const childs = new Set();
    //hooke标识,用来标识是否已经存在子进行了
    let hadHook = false;
    
    //启动任意一下子进和的时候,就放置一个钩子,
    //并且只有第一次存放子进程的时候会放置钩子,
    //钩子只会执行一次(once的特性)
    function gracefull(proc) {
      // 保存子进程引用
      childs.add(proc);
    
      // 设置一次钩子
      /* istanbul ignore else */
      if (!hadHook) {
        hadHook = true;
        let signal;
        [ 'SIGINT', 'SIGQUIT', 'SIGTERM' ].forEach(event => {
          process.once(event, () => {
            signal = event;
            process.exit(0);
          });
        });
        //主进程退出,自动销毁子进程
        process.once('exit', () => {
          // had test at my-helper.test.js, but coffee can't collect coverage info.
          for (const child of childs) {
            debug('kill child %s with %s', child.pid, signal);
            child.kill(signal);
          }
        });
      }
    }
    
    /**
     *  封装fork起动子进程, 返回promise并且优雅的退出
     * @method helper#forkNode
     * @param {String} modulePath - bin path
     * @param {Array} [args] - arguments
     * @param {Object} [options] - options
     * @return {Promise} err or undefined
     * @see https://nodejs.org/api/child_process.html#child_process_child_process_fork_modulepath_args_options
     */
    exports.forkNode = (modulePath, args = [], options = {}) => {
      options.stdio = options.stdio || 'inherit';
      debug('Run fork `%s %s %s`', process.execPath, modulePath, args.join(' '));
      const proc = cp.fork(modulePath, args, options);
      gracefull(proc);
    
      return new Promise((resolve, reject) => {
        proc.once('exit', code => {
          childs.delete(proc);
          if (code !== 0) {
            const err = new Error(modulePath + ' ' + args + ' exit with code ' + code);
            err.code = code;
            reject(err);
          } else {
            resolve();
          }
        });
      });
    };
    
    /**
     *  封装fork起动子进程, 返回promise并且优雅的退出
     * @method helper#forkNode
     * @param {String} cmd - command
     * @param {Array} [args] - arguments
     * @param {Object} [options] - options
     * @return {Promise} err or undefined
     * @see https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options
     */
    exports.spawn = (cmd, args = [], options = {}) => {
      options.stdio = options.stdio || 'inherit';
      debug('Run spawn `%s %s`', cmd, args.join(' '));
    
      return new Promise((resolve, reject) => {
        const proc = cp.spawn(cmd, args, options);
        gracefull(proc);
        proc.once('error', err => {
          /* istanbul ignore next */
          reject(err);
        });
        proc.once('exit', code => {
          childs.delete(proc);
    
          if (code !== 0) {
            return reject(new Error(`spawn ${cmd} ${args.join(' ')} fail, exit code: ${code}`));
          }
          resolve();
        });
      });
    };
    
    /**
     * 执行npm install
     * @method helper#npmInstall
     * @param {String} npmCli - npm cli, such as `npm` / `cnpm` / `npminstall`
     * @param {String} name - node module name
     * @param {String} cwd - target directory
     * @return {Promise} err or undefined
     */
    exports.npmInstall = (npmCli, name, cwd) => {
      const options = {
        stdio: 'inherit',
        env: process.env,
        cwd,
      };
    
      const args = [ 'i', name ];
      console.log('[common-bin] `%s %s` to %s ...', npmCli, args.join(' '), options.cwd);
    
      return exports.spawn(npmCli, args, options);
    };
    
    /**
     * 调用方法
     * @method helper#callFn
     * @param {Function} fn - support generator / async / normal function return promise
     * @param {Array} [args] - fn args
     * @param {Object} [thisArg] - this
     * @return {Object} result
     */
    exports.callFn = function* (fn, args = [], thisArg) {
      if (!is.function(fn)) return;
      if (is.generatorFunction(fn)) {
        return yield fn.apply(thisArg, args);
      }
      const r = fn.apply(thisArg, args);
      if (is.promise(r)) {
        return yield r;
      }
      return r;
    };
    
    /**
     * unparse argv and change it to array style
     * @method helper#unparseArgv
     * @param {Object} argv - yargs style
     * @param {Object} [options] - options, see more at https://github.com/sindresorhus/dargs
     * @param {Array} [options.includes] - keys or regex of keys to include
     * @param {Array} [options.excludes] - keys or regex of keys to exclude
     * @return {Array} [ '--debug=7000', '--debug-brk' ]
     */
    exports.unparseArgv = (argv, options = {}) => {
      // revert argv object to array
      // yargs will paser `debug-brk` to `debug-brk` and `debugBrk`, so we need to filter
      return [ ...new Set(unparse(argv, options)) ];
    };
    
    /**
     * extract execArgv from argv
     * @method helper#extractExecArgv
     * @param {Object} argv - yargs style
     * @return {Object} { debugPort, debugOptions: {}, execArgvObj: {} }
     */
    exports.extractExecArgv = argv => {
      const debugOptions = {};
      const execArgvObj = {};
      let debugPort;
    
      for (const key of Object.keys(argv)) {
        const value = argv[key];
        // skip undefined set uppon (camel etc.)
        if (value === undefined) continue;
        // debug / debug-brk / debug-port / inspect / inspect-brk / inspect-port
        if ([ 'debug', 'debug-brk', 'debug-port', 'inspect', 'inspect-brk', 'inspect-port' ].includes(key)) {
          if (typeof value === 'number') debugPort = value;
          debugOptions[key] = argv[key];
          execArgvObj[key] = argv[key];
        } else if (match(key, [ 'es_staging', 'expose_debug_as', /^harmony.*/ ])) {
          execArgvObj[key] = argv[key];
        } else if (key.startsWith('node-options--')) {
          // support node options, like: commond --node-options--trace-warnings => execArgv.push('--trace-warnings')
          execArgvObj[key.replace('node-options--', '')] = argv[key];
        }
      }
      return { debugPort, debugOptions, execArgvObj };
    };
    
    function match(key, arr) {
      return arr.some(x => x instanceof RegExp ? x.test(key) : x === key); // eslint-disable-line no-confusing-arrow
    }
  • 相关阅读:
    js精度溢出解决方案
    Maven的Archetype简介
    maven仓库--私服(Nexus的配置使用)
    maven snapshot和release版本的区别
    jar包版本介绍(beta,alpha,release),软件的版本介绍
    最全的maven的pom.xml文件详解
    私服仓库 nexus 环境搭建(win10)
    EL表达式不解析
    Hibernate框架 主配置文件(Hibernate.cfg.xml)基本
    出现 The processing instruction target matching "[xX][mM][lL]" is not allowed错误
  • 原文地址:https://www.cnblogs.com/hellolol/p/11474498.html
Copyright © 2011-2022 走看看