• Stars
    star
    189
  • Rank 200,511 (Top 5 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created almost 8 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Abstraction bin tool

common-bin

NPM version Node.js CI Test coverage Known Vulnerabilities npm download

Abstraction bin tool wrap yargs, to provide more convenient usage, support async / await style.


Install

$ npm i common-bin

Build a bin tool for your team

You maybe need a custom xxx-bin to implement more custom features.

Now you can implement a Command sub class to do that.

Example: Write your own git command

This example will show you how to create a new my-git tool.

test/fixtures/my-git
β”œβ”€β”€ bin
β”‚   └── my-git.js
β”œβ”€β”€ command
β”‚   β”œβ”€β”€ remote
β”‚   β”‚   β”œβ”€β”€ add.js
β”‚   β”‚   └── remove.js
β”‚   β”œβ”€β”€ clone.js
β”‚   └── remote.js
β”œβ”€β”€ index.js
└── package.json

my-git.js

#!/usr/bin/env node

'use strict';

const Command = require('..');
new Command().start();

Main Command

Just extend Command, and use as your bin start point.

You can use this.yargs to custom yargs config, see http://yargs.js.org/docs for more detail.

const Command = require('common-bin');
const pkg = require('./package.json');

class MainCommand extends Command {
  constructor(rawArgv) {
    super(rawArgv);
    this.usage = 'Usage: my-git <command> [options]';

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

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

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

module.exports = MainCommand;

CloneCommand

const Command = require('common-bin');
class CloneCommand extends Command {
  constructor(rawArgv) {
    super(rawArgv);

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

  async run({ argv }) {
    console.log('git clone %s to %s with depth %d', argv._[0], argv._[1], argv.depth);
  }

  get description() {
    return 'Clone a repository into a new directory';
  }
}

module.exports = CloneCommand;

Run result

$ my-git clone gh://node-modules/common-bin dist --depth=1

git clone gh://node-modules/common-bin to dist with depth 1

Concept

Command

Define the main logic of command

Method:

  • async start() - start your program, only use once in your bin file.
  • async run(context)
    • should implement this to provide command handler, will exec when not found sub command.
    • Support generator / async function / normal function which return promise.
    • context is { cwd, env, argv, rawArgv }
      • cwd - process.cwd()
      • env - clone env object from process.env
      • argv - argv parse result by yargs, { _: [ 'start' ], '$0': '/usr/local/bin/common-bin', baseDir: 'simple'}
      • rawArgv - the raw argv, [ "--baseDir=simple" ]
  • load(fullPath) - register the entire directory to commands
  • add(name, target) - register special command with command name, target could be full path of file or Class.
  • alias(alias, name) - register a command with an existing command
  • showHelp() - print usage message to console.
  • options= - a setter, shortcut for yargs.options
  • usage= - a setter, shortcut for yargs.usage

Properties:

  • description - {String} a getter, only show this description when it's a sub command in help console
  • helper - {Object} helper instance
  • yargs - {Object} yargs instance for advanced custom usage
  • options - {Object} a setter, set yargs' options
  • version - {String} customize version, can be defined as a getter to support lazy load.
  • parserOptions - {Object} control context parse rule.
    • execArgv - {Boolean} whether extract execArgv to context.execArgv
    • removeAlias - {Boolean} whether remove alias key from argv
    • removeCamelCase - {Boolean} whether remove camel case key from argv

You can define options by set this.options

this.options = {
  baseDir: {
    alias: 'b',
    demandOption: true,
    description: 'the target directory',
    coerce: str => path.resolve(process.cwd(), str),
  },
  depth: {
    description: 'level to clone',
    type: 'number',
    default: 1,
  },
  size: {
    description: 'choose a size',
    choices: ['xs', 's', 'm', 'l', 'xl']
  },
};

You can define version by define this.version getter:

get version() {
  return 'v1.0.0';
}

Helper

  • async forkNode(modulePath, args, opt) - fork child process, wrap with promise and gracefull exit
  • async spawn(cmd, args, opt) - spawn a new process, wrap with promise and gracefull exit
  • async npmInstall(npmCli, name, cwd) - install node modules, wrap with promise
  • async callFn(fn, args, thisArg) - call fn, support gernerator / async / normal function return promise
  • unparseArgv(argv, opts) - unparse argv and change it to array style

Extend Helper

// index.js
const Command = require('common-bin');
const helper = require('./helper');
class MainCommand extends Command {
  constructor(rawArgv) {
    super(rawArgv);

    // load sub command
    this.load(path.join(__dirname, 'command'));

    // custom helper
    Object.assign(this.helper, helper);
  }
}

Advanced Usage

Single Command

Just need to provide options and run().

const Command = require('common-bin');
class MainCommand extends Command {
  constructor(rawArgv) {
    super(rawArgv);
    this.options = {
      baseDir: {
        description: 'target directory',
      },
    };
  }

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

Sub Command

Also support sub command such as my-git remote add <name> <url> --tags.

// test/fixtures/my-git/command/remote.js
class RemoteCommand extends Command {
  constructor(rawArgv) {
    // DO NOT forgot to pass params to super
    super(rawArgv);
    // load sub command for directory
    this.load(path.join(__dirname, 'remote'));
  }

  async run({ argv }) {
    console.log('run remote command with %j', argv._);
  }

  get description() {
    return 'Manage set of tracked repositories';
  }
}

// test/fixtures/my-git/command/remote/add.js
class AddCommand extends Command {
  constructor(rawArgv) {
    super(rawArgv);

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

  }

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

  get description() {
    return 'Adds a remote named <name> for the repository at <url>';
  }
}

see remote.js for more detail.

Async Support

class SleepCommand extends Command {
  async run() {
    await sleep('1s');
    console.log('sleep 1s');
  }

  get description() {
    return 'sleep showcase';
  }
}

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

see async-bin for more detail.

Bash-Completions

$ # exec below will print usage for auto bash completion
$ my-git completion
$ # exec below will mount auto completion to your bash
$ my-git completion >> ~/.bashrc

Bash-Completions

Migrating from v1 to v3

bin

  • run method is not longer exist.
// 1.x
const run = require('common-bin').run;
run(require('../lib/my_program'));

// 3.x
// require a main Command
const Command = require('..');
new Command().start();

Program

  • Program is just a Command sub class, you can call it Main Command now.
  • addCommand() is replace with add().
  • Recommand to use load() to load the whole command directory.
// 1.x
this.addCommand('test', path.join(__dirname, 'test_command.js'));

// 3.x
const Command = require('common-bin');
const pkg = require('./package.json');

class MainCommand extends Command {
  constructor() {
    super();

    this.add('test', path.join(__dirname, 'test_command.js'));
    // or load the entire directory
    this.load(path.join(__dirname, 'command'));
  }
}

Command

  • help() is not use anymore.
  • should provide name, description, options.
  • async run() arguments had change to object, recommand to use destructuring style - { cwd, env, argv, rawArgv }
    • argv is an object parse by yargs, not args.
    • rawArgv is equivalent to old args
// 1.x
class TestCommand extends Command {
  * run(cwd, args) {
    console.log('run mocha test at %s with %j', cwd, args);
  }
}

// 3.x
class TestCommand extends Command {
  constructor() {
    super();
    // my-bin test --require=co-mocha
    this.options = {
      require: {
        description: 'require module name',
      },
    };
  }

  async run({ cwd, env, argv, rawArgv }) {
    console.log('run mocha test at %s with %j', cwd, argv);
  }

  get description() {
    return 'unit test';
  }
}

helper

  • getIronNodeBin is remove.
  • child.kill now support signal.

License

MIT

Contributors


atian25


fengmk2


popomore


dead-horse


whxaxes


DiamondYuan


tenpend


hacke2


liuqipeng417


Jarvis2018

This project follows the git-contributor spec, auto updated at Sat Jun 04 2022 00:31:29 GMT+0800.

More Repositories

1

utility

A collection of useful utilities.
TypeScript
1,239
star
2

parameter

A parameter verify tools.
JavaScript
727
star
3

urllib

Request HTTP(s) URLs in a complex world.
TypeScript
725
star
4

agentkeepalive

Support keepalive http agent.
JavaScript
571
star
5

emoji

emoji: This library allows the handling and conversion of Emoji in Javascript.
HTML
502
star
6

weibo

weibo nodejs sdk
JavaScript
489
star
7

compressing

Everything you need for compressing and uncompressing
JavaScript
424
star
8

detect-port

Node.js module to detect available ports of the system.
JavaScript
376
star
9

qn

Another qiniu http://docs.qiniu.com/api/ API client for Node.js.
JavaScript
274
star
10

graceful

Graceful exit when `uncaughtException` emit, base on `process.on('uncaughtException')`.
JavaScript
249
star
11

address

Get current machine IP and MAC address.
TypeScript
228
star
12

autod

Auto generate dependencies and devDependencies by parse the project file.
JavaScript
205
star
13

js-to-java

easy way to wrap js object to java object
JavaScript
201
star
14

hessian.js

js hessian binary web service protocol, support communicate with java
JavaScript
183
star
15

mm

An simple but flexible mock(or say stub) package, mock mate
JavaScript
158
star
16

cfork

cluster fork and restart easy way
JavaScript
156
star
17

formstream

multipart/form-data encoded stream, helper for file upload.
JavaScript
145
star
18

urlencode

encodeURIComponent with charset
TypeScript
142
star
19

cluster-client

Sharing Connection among Multi-Process Nodejs
JavaScript
131
star
20

webcamera

网鑡ζˆͺε›Ύε·₯ε…· (by phantomjs)
JavaScript
124
star
21

is-type-of

complete type checking for node
TypeScript
122
star
22

coffee

Test command line on Node.js
JavaScript
97
star
23

clet

Command Line E2E Testing
JavaScript
76
star
24

byte

Input Buffer and Output Buffer, just like Java ByteBuffer
JavaScript
76
star
25

sdk-base

a base class for sdk with default error handler
JavaScript
62
star
26

china-mobile-phone-regexp

The regular expressions for China mobile phone number.
JavaScript
60
star
27

mz-modules

Same as `mz`, but wrap modules in the world rather than core API.
JavaScript
56
star
28

thunkify-wrap

a more powerful thunkify
JavaScript
55
star
29

ots

This project no longer maintained, please use https://github.com/ali-sdk/ots2 instead.
JavaScript
48
star
30

urllib-sync

sync http request
JavaScript
44
star
31

stream-wormhole

Pipe ReadStream to a wormhole
TypeScript
42
star
32

copy-to

copy an object's properties to another one
JavaScript
41
star
33

optimized

Detect a function can be optimized or not.
JavaScript
41
star
34

runscript

Run script easy!
JavaScript
41
star
35

await-stream-ready

a promise waiting stream ready
JavaScript
34
star
36

charset

Get the content charset from header and html content-type.
JavaScript
34
star
37

ab

A benchmark tool.
JavaScript
33
star
38

npm-updater

Prompt update of npm package
JavaScript
32
star
39

java.io

A Node.js implement of "java.io.InputObjectStream.readObject()" and "java.io.OutputObjectStream.writeObject()"
JavaScript
31
star
40

humanize-ms

transform humanize time to ms
JavaScript
30
star
41

graceful-process

graceful exit process even parent exit on SIGKILL.
JavaScript
29
star
42

node-murmurhash

murmurhash, support utf8 Buffer
JavaScript
27
star
43

sendmessage

Send a cross process message if message channel is connected.
JavaScript
27
star
44

shameimaru

Shameimaru Aya likes to traverse node_modules and capture the tree.
JavaScript
26
star
45

ready-callback

Launch server after all async task ready
TypeScript
26
star
46

tcp-base

TCP client base
JavaScript
25
star
47

serialize-json

A serialize algorithm for JSON
JavaScript
23
star
48

js-remoting-for-apache-dubbo

dubbo protocol implement
JavaScript
22
star
49

loading

loading dir files as module to an object
JavaScript
20
star
50

zookeeper-cluster-client

Sharing one zookeeper connection among Multi-Process on Node.js
JavaScript
20
star
51

tnpm

JavaScript
19
star
52

enable

Detect es6 features enable or not.
JavaScript
19
star
53

last-commit-log

Node.js module to get the last git commit information - mostly to be used by CI/CD and building phase.
JavaScript
19
star
54

jdwp

Java Debug Wire Protocol
JavaScript
18
star
55

time-profile

Measuring execution time of functions
JavaScript
16
star
56

qps

High performance qps counter
JavaScript
15
star
57

cluster-reload

Easy and safe reload your workers.
JavaScript
14
star
58

await-first

Wait the first event in a set of event pairs, then clean up after itself.
JavaScript
14
star
59

buffer-type

Detect content-type from Buffer data.
JavaScript
14
star
60

pedding

Just pedding for callback.
JavaScript
13
star
61

should2assert

A tool to help you migrating from should to assert
JavaScript
13
star
62

save-file-atomic

Save anything to file atomic
JavaScript
13
star
63

wt

wt: Simple dir watcher, support events
JavaScript
13
star
64

zlogger

The last console logger
JavaScript
12
star
65

logfilestream

Log stream, including auto rolling feature, support multiprocess `append` write at the same time.
JavaScript
12
star
66

dns-hijacking

JavaScript
11
star
67

default-user-agent

Default user agent string for Node.js http request
JavaScript
11
star
68

jsonp-body

Helper to create more safe jsonp response body for koa and other web framework.
JavaScript
10
star
69

zookeeper-watcher

Extend node-zookeeper-client, let zookeeper client support `watch(path)` method.
JavaScript
10
star
70

weibo-mid

Convert Weibo Open API mid to base62 hash string.
JavaScript
10
star
71

connection

JavaScript
10
star
72

enums

JavaScript
9
star
73

node-homedir

Get the effective user's homedir
TypeScript
9
star
74

rid

Request Unique ID, base on current server `ip`, `process.pid` and auto increase id, like `$ip,$pid,$id`
JavaScript
9
star
75

error-formatter

format an error into string or json for log
JavaScript
8
star
76

auto-correct

auto correct for command line tools
JavaScript
8
star
77

install-node

Install node into node_modules
JavaScript
8
star
78

digest-header

Digest access authentication header helper
JavaScript
8
star
79

http-doctor

HTTP doctor
JavaScript
7
star
80

vmto

velocity(vm) to any other templates.
JavaScript
7
star
81

restful-client

RESTFul api client base object. Usually use by some api client implementation.
JavaScript
6
star
82

diskstore

a local cache implement
JavaScript
6
star
83

koa-override

method override middleware for koa
JavaScript
6
star
84

memory-tripwire

suicide when memory over the limit
JavaScript
5
star
85

urlmock

Easy load mock data from a specify url.
JavaScript
5
star
86

performance-ms

performance timer in ms
TypeScript
4
star
87

common-bin-plus

advanced common-bin for cli usage
JavaScript
4
star
88

aggregate-base

Base class for aggregate operation
JavaScript
4
star
89

watch-files

watch files by polling
JavaScript
3
star
90

oss-syncer

synchronization all files from this bucket to another bucket
JavaScript
3
star
91

common-boilerplate

base class for boilerplate
JavaScript
3
star
92

fileloader

more stable file loader for nunjucks, and support charsets like `gbk`.
JavaScript
3
star
93

assert-file

assert file utilities
JavaScript
3
star
94

changing

Watching `file`, `dir` or `link` changing, using interval timer.
JavaScript
3
star
95

speeds

Speeds controllable stream. You can control the downstream speed on your own.
JavaScript
3
star
96

cov

Mocha Coverage report store on CDN.
JavaScript
3
star
97

onelogger

The only ONE logger
TypeScript
3
star
98

sse-decoder

SSE decoder for nodejs
TypeScript
3
star
99

fast-ua-parser

A Fast JavaScript library to detect user's Browser, Engine, OS, CPU, and Device type/model
2
star
100

get-ready

NodeJS mixin to add one-time ready event
TypeScript
2
star