@2fd/command

中文文档
1.1.3发布于 2026/11/02MITTypeScriptCommonJS零依赖构建来源已验证近 30 天下载 5.1万

模块命令行工具

中文使用文档
文档目录19 节
  1. 安装
  2. 目标
  3. 快开始
  4. 图标
  5. Command (类)
  6. 快速命令( 函数)
  7. 参数
  8. 旗帜
  9. 执行器( 多命令工具)
  10. 懒惰的加载路径
  11. 执行者可以筑巢
  12. 投入和产出
  13. ArgvInput(argv, exec?)
  14. 产出
  15. 处理错误
  16. 扩展
  17. API 参考
  18. 发展
  19. 许可证

@ 2fd/ 命令 test

在Node.js中构建命令行工具的模块化,面向对象的框架, 包含 TypeScript 定义.

零从属. @2fd/command 没有运行时间依赖: 安装 它在你的包里加了一个 node_modules。唯一的依赖关系 是 TypeScript,用于编译源.

安装

npm install --save @2fd/command

支持的 Node.js 版本是 CI 测试的版本: 从 0.12至26 (英语).

支持的TypeScript版本是CI测试的版本: 2.0, 2.4, 2.9, 3.9, 4.9, 5.x, 6.x 和最新发布. 这个 types 任务安装打包 软件包输入 compat/ 并用每个版本检查它。 TS 2.0 电话 改为 5.x 使用 moduleResolution: node,和 TS 5.x 并随后使用 nodenext 与 strict。 。 。 .

目标

  • 无依取相. 没有别的东西被拉入你的树里,所以有 没有用于审计、更新或补丁的中转软件包.

  • 懒装入. 命令可以注册为指向它的字符串 模块('./commands#migrate') (中文(简体) ). 模块只是 required 当 命令运行(或当帮助被打印时),那么大的工具快速启动.

  • 命令名属于工具而非包. 那个工具 注册命令决定如何引用(migration:init, (中文(简体) ), mgt:i(中文(简体) ). 第三方包导出命令; 您选择需要的, 重命名 或者换成你自己的.

  • 完全模块化. 命令、参数、旗帜、输入和输出都很小 界面后面的物体,所以任何一块都可以共享,替换或扩展.

  • 已打出字来. 装有包件的船舶类型定义index.d.ts(无) typings编号 :@types 需要安装。 用 TypeScript 2.0 向上测试 至最新版本(见 安装) (中文(简体) ).

快开始

// cli.js
const {
    Command,
    ExecutorCommand,
    Param,
    BooleanFlag,
    ValueFlag,
    ArgvInput,
    ConsoleOutput,
} = require('@2fd/command');

class Greet extends Command {
    constructor() {
        super();
        this.description = 'Greet someone';
        this.params = new Param('name [...others]');
        this.flags = [
            new BooleanFlag('loud', ['--loud', '-l'], 'Uppercase the greeting'),
            new ValueFlag('times', ['--times', '-t'], 'Repeat N times', Number, 1),
        ];
    }

    action(input, output) {
        const names = [input.params.name, ...(input.params.others || [])];
        let msg = 'Hello ' + names.join(', ');

        if (input.flags.loud)
            msg = msg.toUpperCase();

        for (let i = 0; i < input.flags.times; i++)
            output.log(msg);
    }
}

const tool = new ExecutorCommand();
tool.version = '1.0.0';
tool.description = 'My tool';
tool.addCommand('greet', new Greet());

tool.handle(new ArgvInput(process.argv), new ConsoleOutput());
$ node cli.js greet Ana Bob -l -t 2
HELLO ANA, BOB
HELLO ANA, BOB

图标

命令是执行命令的任何对象 CommandInterface数字 :

interface CommandInterface<F, P> {
    description: string;
    handle(input: InputInterface<F, P>, output: OutputInterface): void;
}

您通常会延长一个内建课程, 而不是执行 直接说.

Command (类)

扩展 Command,定义 description, (中文(简体) ), params 财务报告和审定财务报表 flags,并执行 action。 。 。 . handle() 解析输入、校验参数和旗帜,然后 电话 action()。 。 。 .

import {
    Command,
    InputInterface,
    OutputInterface,
    Param,
    BooleanFlag,
} from '@2fd/command';

type Flags = { force: boolean };
type Params = { requireParam: string; optionalParam?: string; optionalParamList?: string[] };

export class MyCommand extends Command<Flags, Params> {

    description = 'My Command description';

    params = new Param('requireParam [optionalParam] [...optionalParamList]');

    flags = [
        new BooleanFlag('force', ['--force', '-f'], 'Force flag'),
    ];

    action(input: InputInterface<Flags, Params>, output: OutputInterface): void {
        // input.params.requireParam       -> string
        // input.params.optionalParam      -> string | undefined
        // input.params.optionalParamList  -> string[] | undefined
        // input.flags.force               -> boolean
    }
}

export const myCommand = new MyCommand();

执行规则 Command数字 :

  • params 需要( 使用 NoParams 或者说 IgnoreParams 没有命令 立场论据).
  • flags 必须是数组(可以是空的).
  • 两面旗帜不能共用 name 或同一选项(例如两个) -f) (中文(简体) ).
  • 未知选项 Unexpected option: <flag>。 。 。 .
  • 帮助旗帜( A)-h, --help自动添加。 当存在时,帮助是 印刷和 action() 没有叫.

独立命令可以运行, 无需执行器 :

// command.js
const { ArgvInput, ConsoleOutput } = require('@2fd/command');
const { myCommand } = require('./commands');

myCommand.handle(new ArgvInput(process.argv), new ConsoleOutput());
$ node command.js --help

    My Command description

    Usage: node command.js [OPTIONS] requireParam [optionalParam] [...optionalParamList]


    [OPTIONS]:
    --force, -f    Force flag
    -h, --help     Print this help

快速命令( 函数)

普通函数 (input, output) => void 可注册为命令. 设置 a description 属性在帮助中显示(默认) 改为 -) (中文(简体) ). 快速命令接收原始输入:没有解析参数/标记, input.argv 包含其余参数.

function ping(input, output) {
    output.log('pong', input.argv);
}
ping.description = 'Reply with pong';

exports.ping = ping;

参数

Param 从定义字符串中解析位置参数。 每个 白空分隔符号定义了一段:

脚本含义数值 input.params
name所需经费string
[name]选项string | undefined
...name需要的列表( 至少一个值)string[]
[...name]可选列表string[] | undefined
new Param('source');
new Param('source [target]');
new Param('...files');
new Param('src1 src2 [optional] [...rest]');

数值按顺序分配。 一个列表参数会消耗所有剩余位置 参数。 丢出额外参数 Unexpected param: <value>; 需要缺失 抛出 Param <name> is required。 。 。 .

其他参数处理器 :

类行为
NoParams任何位置参数 Unexpected param。 。 。 .
IgnoreParams立场论点被默默地忽略了.

旗帜

每一面旗帜都要 (name, list, description)数字 :

  • name: 使用的密钥 input.flags。 。 。 .
  • list: 激活旗帜的选项, 例如 . ['--force', '-f']。 。 。 .
  • description: 帮助中显示的文本。 要求, 不能为空 .
类数值 input.flags[name]
BooleanFlag(name, list, desc)true 如果有的话,否则 false。 。 。 .
ValueFlag(name, list, desc, parser?, default?)下一个辩论,通过 parser 如果给出. default 缺席,否则 undefined。 。 。 .
ListValueFlag(name, list, desc, parser?, default?)数值矩阵,每起发生一次(--tag a --tag b) (中文(简体) ). default (或 []如缺席.
RequireFlag(flag)如果值为 undefined, (中文(简体) ), null, (中文(简体) ), NaN 或为空.
HelpFlag()布尔 help 打开旗子 -h, --help自动添加.
NullFlag()无上正旗.
const {
    BooleanFlag, ValueFlag, ListValueFlag, RequireFlag,
} = require('@2fd/command');

this.flags = [
    new BooleanFlag('dryRun', ['--dry-run', '-n'], 'Do not write anything'),
    new ValueFlag('port', ['--port', '-p'], 'Port to listen on', Number, 8080),
    new ListValueFlag('env', ['--env', '-e'], 'Environment variable (repeatable)'),
    new RequireFlag(
        new ValueFlag('config', ['--config', '-c'], 'Config file path')
    ),
];

解析注释 :

  • 任何从 - 被当成一面旗帜.
  • 数值作为单独的参数传递(--port 80) (中文(简体) ). --port=80 财务报告和审定财务报表 分组短旗( u)-abc)不支持.
  • 无法从 -· ; --port -1 掷出 Flag port (--port, -p) expect a value。 。 。 .

执行器( 多命令工具)

ExecutorCommand 将第一个位置参数导出到已注册的命令 并转达其余的论据.

const { ExecutorCommand, ArgvInput, ColorConsoleOutput } = require('@2fd/command');
const { myCommand } = require('./commands');

const tool = new ExecutorCommand();
tool.version = '1.0.0';
tool.description = 'My tool';

// Command instance
tool.addCommand('run', myCommand);

// Lazy loaded: "<module path>#<export name>"
tool.addCommand('build', './lib/commands#build');

// Lazy loaded: the module itself is the command (module.exports = ...)
tool.addCommand('clean', './lib/commands/clean');

// Several at once
tool.addCommands({
    'start': './lib/commands#start',
    'stop':  './lib/commands#stop',
});

// Namespaced: registered as "db:migrate" and "db:seed"
tool.addCommadsNS('db', {
    'migrate': './lib/commands/db#migrate',
    'seed':    './lib/commands/db#seed',
});

tool.handle(new ArgvInput(process.argv), new ColorConsoleOutput());

在没有命令(或不明命令)的情况下运行会打印帮助. 图标 首先列出名称空间,然后按字母顺序排列:

$ node cli.js

    My tool [v1.0.0]

    Usage: node cli.js [OPTIONS] [COMMAND]


    [COMMAND]:
    build         Build the project
    clean         Remove build output
    run           My Command description
    start         Start the server
    stop          Stop the server
    db:migrate    Run migrations
    db:seed       Seed the database

    [OPTIONS]:
    -h, --help    Print this help

懒惰的加载路径

字符串命令有格式 <module>[#<export>]数字 :

  • <module> 从开始 . 解决 反对 process.cwd()没有 对登记它的文件。 对于能够运行于任意的工具 目录,使用绝对路径 :

    const { join } = require('path');
    tool.addCommand('build', join(__dirname, 'lib/commands') + '#build');
    
  • 任何其他 <module> 以 require.resolve (包装名称, 绝对路径 : 'some-package/commands#migrate'。 。 。 .

  • 无 #<export>,则使用模块导出本身.

  • 导出可以是命令对象或快速命令功能.

懒惰命令在运行或执行器帮助被打印时被加载 (阅读其 description) (中文(简体) ).

执行者可以筑巢

ExecutorCommand 本身是一个命令,所以可以在另一个命令内注册 执行器以建立更深层次的命令树 .

投入和产出

ArgvInput(argv, exec?)

环绕 process.argv。它删除了节点.js可执行和脚本路径 argv 并储存在 exec,用于打印 Usage: 线条. 如果剧本生活在一个 PATH 目录(全球安装) bin),只有 脚本名称显示 .

interface InputInterface<F, P> {
    argv: string[];   // arguments not consumed yet
    exec: string[];   // how the tool was invoked, e.g. ['node', 'cli.js']
    flags: F;         // parsed flags
    params: P;        // parsed params
}

产出

类行为
ConsoleOutput写给 console.log 编号 : console.error。 。 。 . %c 样式被剥去.
ColorConsoleOutput一样,但翻译 %c CSS等风格为ANSI颜色. error() 是红色的.

双方支持 util.format 占位符 (%s, (中文(简体) ), %d, (中文(简体) ), %j) 加上浏览器 控制台占位符 %i, (中文(简体) ), %f, (中文(简体) ), %o, (中文(简体) ), %O 财务报告和审定财务报表 %c数字 :

output.log('%cdone%c in %dms', 'color:green;font-weight:bold', '', 120);
output.error('Cannot open %s', file);

支助 %c 样式 : color:<name>, (中文(简体) ), background:<name> 编号 : background-color:<name>, (中文(简体) ), font-weight:bold|normal, (中文(简体) ), font-style:italic, (中文(简体) ), text-decoration:underline|line-through, (中文(简体) ), visibility:hidden。 。 。 . 颜色名称 : black, (中文(简体) ), red, (中文(简体) ), green, (中文(简体) ), yellow, (中文(简体) ), blue, (中文(简体) ), magenta, (中文(简体) ), cyan, (中文(简体) ), white, (中文(简体) ), gray编号 :grey (无) gray 页:1.

任何对象 log() 财务报告和审定财务报表 error() 方法可作为输出(用于 例如,在测试中捕获输出).

处理错误

解析和校验错误作为正则 Errors和现在 没有 被图书馆抓住了 环绕 handle() 并设置 退出代码 :

try {
    tool.handle(new ArgvInput(process.argv), output);
} catch (err) {
    output.error(err.message);
    process.exitCode = 1;
}

库出错 :

消息原因
Unexpected option: <flag>未知旗帜.
Unexpected param: <value>太多的立场争论.
Param <name> is required缺少所需的参数.
Flag <name> (<list>) expect a valueValueFlag编号 :ListValueFlag 无值.
Flag <name> (<list>) is requiredRequireFlag 未提供.
Cannot overwrite flag ...复制旗名或选项 .
<export> not found in <path>Lazy 命令导出不存在 .

扩展

自定义旗和参数执行三个钩子的小接口,调用 此顺序由 Command.handle()数字 :

  1. before(input, output):一次,在解析前. 在此设定默认值 .
  2. parse(arg, input, output): 每个匹配参数。 旗帜可以消耗 其数值与 input.argv.shift()。 。 。 .
  3. after(input, output): 一次, 解析后( 跳过何时) --help 实值 (现) 在这里验证或正常化.
interface FlagInterface<F> {
    name: string;
    description: string;
    list: string[];
    before(input, output): void;
    parse(flag: string, input, output): void;
    after(input, output): void;
}

interface ParamInterface<P> {
    definition: string;           // shown in the "Usage:" line
    before(input, output): void;
    parse(param: string, input, output): void;
    after(input, output): void;
}

示例: 反向旗 (-v -v -v → 3) (中文(简体) ).

const { FlagConstructor } = require('@2fd/command');

class CountFlag extends FlagConstructor {
    before(input) { input.flags[this.name] = 0; }
    parse(flag, input) { input.flags[this.name]++; }
    after() { }
}

new CountFlag('verbose', ['--verbose', '-v'], 'Increase verbosity');

要自定义帮助, 请覆盖 helpDescription(), (中文(简体) ), helpUsage(executable) 或者说 helpOptions() 在命令中,或用设置替换帮助旗 helpFlag 第一次选举之前 handle() 电话.

API 参考

下面的一切都是从 @2fd/command。 。 。 .

导出仁爱说明
Command类使用参数和旗帜命令的下级.
ExecutorCommand类路由子命令;支持懒惰加载.
Param类定义字符串中的位置参数 .
NoParams类拒绝位置参数 .
IgnoreParams类忽略位置参数 .
FlagConstructor类验证的基础类 name, (中文(简体) ), list, (中文(简体) ), description。 。 。 .
BooleanFlag类true编号 :false 旗帜.
ValueFlag类有单一值的旗帜 .
ListValueFlag类可重复带有数值列表的旗帜 .
RequireFlag类做一个包裹的旗帜需要.
HelpFlag类-h, --help。 。 。 .
NullFlag类无上正旗.
ArgvInput类输入来自 process.argv。 。 。 .
ConsoleOutput类普通控制台输出 .
ColorConsoleOutput类使用 ANSI 颜色的控制台输出 .
CommandInterface接口任何命令的合同.
InputInterface接口输入对象合同.
OutputInterface接口产出对象合同.

发展

npm install
npm run compile       # tsc -p .
npm run declaration   # generate .d.ts files
npm test              # mocha (run compile first)

许可证

麻省理工学院

版本与发布记录

@2fd/command 共发布 13 个版本,首次发布于 2016/05/02;过去 12 个月发布了 1 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
1.1.3latest2026/11/026 天前
1.1.22016/11/209 年前
1.1.12016/11/209 年前
1.1.02016/08/2910 年前
1.0.12016/08/2310 年前
1.0.02016/07/0510 年前

关于 @2fd/command 的常见问题

@2fd/command 是什么?

模块命令行工具

如何安装 @2fd/command?

在项目目录运行 npm install @2fd/command,或使用 pnpm add / yarn add / bun add。

@2fd/command 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@2fd/command 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@2fd/command 可以商用吗?

@2fd/command 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@2fd/command 的下载量有多少?

根据 npm 官方下载统计,@2fd/command 在 2026/10/05 – 2026/11/03 这 30 天内被下载 50,644 次,日均约 1,688 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@2fd/command 还在维护吗?

最新版本 1.1.3 发布于 2026/11/02(6 天前);至今共发布 13 个版本,其中过去 12 个月发布了 1 个;首次发布于 2016/05/02。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。