question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[RFC] common-bin refactor

See original GitHub issue

背景

目前的 common-bin 有点简陋,缺少:

  • 参数的处理和校验
  • help 的自动输出

方案

基于 yargs 进行改造,干掉 commander.js

Program

  • Program 这概念没了,就是一个 Command 的子类而已,可以叫它 Main Command
  • start() 为 bin 的启动入口
  • loadCommand(...args) 用于加载子命令,其中会被 path.join 拼起来
  • addCommand(...args) 用于加载子命令
// index.js
const BaseCommand = require('common-bin');
const pkg = require('../package.json';

class Command extends BaseCommand {
  constructor() {
    super();
    this.name = pkg.name;
    this.usage = `Usage: ${this.name} <command> [options]`;

    // load entire command directory
    this.loadCommand(__dirname, 'command');

    // or load special command file
    // this.addCommand(__dirname, 'test_command.js');

    // more custom with `yargs` api, such as you can use `my-git -V`
    this.yargs.alias('V', 'version');
  }
}

在 bin 里面调用方式修改为:

// bin/my-bin.js
const Command = require('..');
new Command().start();

Command

  • run
  • 入参变为 object 形式,要注意是 argv 而不是原来的 args
  • 支持 generator / async function / normal function which return promise
  • name 为命令名称
    • 支持 clone <repository> [directory] 的形式
  • description 是命令描述,不提供的话则为隐藏命令
  • options 属性来配置命令行的约束,参见yargs#options
  • aliases 为命令别名,支持字符串或数组
  • help() 方法不再需要
  • loadCommand(...args) 用于加载子命令目录,其中会被 path.join 拼起来
  • addCommand(filePath) 用于加载子命令
const Command = require('common-bin');

class CloneCommand extends Command {
  constructor() {
    super();
    this.name = 'clone <repository> [directory]';
    this.description = 'Clone a repository into a new directory';

    this.options = {
      depth: {
        type: 'number',
        description: 'Create a shallow clone with a history truncated to the specified number of commits',
      },
    };
  }

  * run({ argv }) {
    console.log('git clone %s to %s with depth %d', argv.repository, argv.directory, argv.depth);
  }
}

module.exports = CloneCommand;

Sub Command

  • my-git remote add <name> <url> --tags
// test/fixtures/my-git/command/remote.js
class RemoteCommand extends Command {
  constructor() {
    super();
    this.name = 'remote';
    this.description = 'Manage set of tracked repositories';
    // load sub command for directory
    this.loadCommand(path.join(__dirname, 'remote'));
  }

  * run({ argv }) {
    // will exec when not sub command match first argument
    console.log('run remote command with %j', argv._);
  }
}

// test/fixtures/my-git/command/remote/add.js
class AddCommand extends Command {
  constructor() {
    super();
    this.name = 'add <name> <url>';
    this.description = 'Adds a remote named <name> for the repository at <url>';

    this.options = {
      tags: {
        type: 'boolean',
        default: false,
        description: 'imports every tag from the remote repository',
      },
    };
  }

  * run({ argv }) {
    console.log('git remote add %s to %s with tags=%s', argv.name, argv.url, argv.tags);
  }
}

Single Command

直接实现 optionsrun() 即可

class Command extends BaseCommand {
  constructor() {
    super();
    this.name = pkg.name;
    this.version = pkg.version;

    this.options = {
      baseDir: {
        description: 'target directory',
      },
    };
  }

  * run(context) {
    console.log('run default command at %s', context.argv.baseDir);
    yield super.run(context);
  }
}

helper

  • getIronNodeBin 不再需要,干掉
  • kill child 支持信号量

兼容性

  • 发布 2.0 版本,不考虑兼容性问题
  • 提供升级指南。

进度

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:40 (40 by maintainers)

github_iconTop GitHub Comments

2reactions
popomorecommented, Mar 5, 2017

load 一层就够了吧,controller 是参数

0reactions
atian25commented, Mar 20, 2017

最终的 API 跟 RFC 稍有不同,以 common-bin README 为准。

Read more comments on GitHub >

github_iconTop Results From Across the Web

Refactor RFC · Issue #53 · node-modules/common-bin · GitHub
Node.js 14.x+ update deps remove generator function forkNode -> execa use clet instead of coffee use jest instead of egg-bin / mocha.
Read more >
Software RFC: ISIS3 SPICE Refactor
This is a general notification that a Request for Comment (RFC) has been opened for proposed changes to the ISIS3 library.
Read more >
draft-ietf-httpbis-semantics-19
Changes from RFC 7233 Refactored the range-unit and ranges-specifier grammars to simplify and reduce artificial distinctions between bytes and other ...
Read more >
Refactoring using type classes and optics
This post is a case study of a refactoring in the jose library demonstrating how ... JWK Set is defined by RFC 7515...
Read more >
Detecting and Refactoring Operational Smells within ... - arXiv
Inter-dependencies are common in the DNS and stem from the hierarchal structure of the ... Comments (RFCs), best practices and policy documents to...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found