node-liftoff 更简单地创建命令行工具

node-liftoff 更简单地创建命令行工具

它是什么?

请参阅此博客文章,查看此概念证明,或继续阅读。

假设您正在编写 CLI 工具。我们称之为 hacker。您想使用 Hackerfile. 这是节点,因此您 hacker 为使用它的每个项目在本地安装。但是,为了 hacker 在 PATH 中获取命令,您还需要全局安装它。

现在,当您运行 hacker 时 ,您希望使用 Hackerfile 当前目录中的配置它的功能,并希望它使用工具的本地安装来执行。此外,如果该 hacker 命令足够智能,可以遍历您的文件夹,直到找到 Hackerfile– 对于您不在项目根目录中的那些时间,那就太好了。哎呀,您甚至可能希望 hacker 通过手动指定工作目录从项目外部的文件夹启动。Liftoff 为您管理这些。

所以,一切都很好。现在,你可以找到你的本地 hackerHackerfile 轻松。不幸的是,事实证明您已经编写 Hackerfile 了咖啡脚本或其他一些 JS 变体。为了支持,你必须为它加载编译器,然后用 node.js 注册它的扩展。好消息,Liftoff 可以做到这一点,而且还有更多。

应用程序接口

constructor(opts)

创建一个 Liftoff 实例来调用您的应用程序。

使用所有选项的示例:

const  Hacker  =  new  Liftoff ( { 

name : 'hacker' ,

processTitle : 'hacker' ,

moduleName : 'hacker' ,

configName : 'hackerfile' ,

extensions : {

'.js' : null ,

'.json' : null ,

'. coffee' : 'coffee-script/register'

} ,

v8flags : [ ' --harmony ' ] // 或 v8flags: require('v8flags')

} );

选项名称

糖用于设置processTitle, moduleName,configName自动。

类型:String

默认:null

这些是等效的:

const  Hacker  =  Liftoff ( { 

processTitle : 'hacker' ,

moduleName : 'hacker' ,

configName : 'hackerfile'

} ) ;

const  Hacker  =  Liftoff ( { name : 'hacker' } ) ;

opts.moduleName

设置您的应用程序在运行时希望在本地找到哪个模块。

类型:String

默认:null

opts.configName

设置 Liftoff 将尝试查找的配置文件的名称。不区分大小写。

类型:String

默认:null

opts.extensions

在搜索配置文件时设置要包含的扩展名。如果需要外部模块来加载给定的扩展(例如.coffee),则应将模块名称指定为键的值。

类型:Object

默认:{".js":null,".json":null}

例子:

在这个例子中,Liftoff 将寻找myappfile{.js,.json,.coffee}. 如果.coffee找到带有扩展名的配置,Liftoff 将尝试coffee-script/require从当前工作目录中获取。

const MyApp = new Liftoff({

name: 'myapp',

extensions: {

'.js': null,

'.json': null,

'.coffee': 'coffee-script/register'

}

});

在这个例子中,Liftoff 将寻找.myapp{rc}.

const MyApp = new Liftoff({

name: 'myapp',

configName: '.myapp',

extensions: {

'rc': null

}

});

在此示例中,Liftoff 将自动尝试为 interpret 支持的任何 javascript 变体加载正确的模块(只要它不需要注册方法)。

const MyApp = new Liftoff({

name: 'myapp',

extensions: require('interpret').jsVariants

});

opts.v8flags

此处指定的任何标志都将应用于节点,而不是您的程序。用于支持诸如myapp --harmony command, where--harmony应该传递给节点而不是您的程序的调用。此功能是使用flagged-respawn 实现的。要支持所有 v8flags,请参阅v8flags。

类型:Array|Function

默认:null

如果这个方法是一个函数,它应该采用一个节点风格的回调来产生一个标志数组。

opts.processTitle

设置进程标题是什么。

类型:String

默认:null

opts.completions(类型)

一种处理 bash/zsh/任何完成的方法。

类型:Function

默认:null

opts.config 文件

要查找的配置文件对象。每个属性都以所找到文件的默认基本名称为键,值是一个以唯一名称为键的路径参数对象。

注意:此选项很有用,例如,如果.apprc除了appfile.js. 如果你只需要一个配置文件,你可能不需要这个。除了让您找到多个文件之外,此选项还允许对配置文件的位置进行更细粒度的控制。

类型:Object

默认:null

路径参数

fined模块接受表示搜索路径的字符串或具有以下键的对象:

  • path (必需的)要搜索的路径。仅使用字符串扩展到此属性。类型:String

    默认:null

  • name要查找的文件的基本名称。在查找期间附加扩展名。类型:String

    默认:顶级键入configFiles

  • extensionsname在查找期间附加到的扩展名。另见:opts.extensions。类型:String|Array|Object

    默认值:opts.extensions

  • cwd的基本目录path(如果是相对的)。类型:String

    默认值:opts.cwd

  • findUp是否path应该向上遍历以查找文件。类型:Boolean

    默认:false

例子:

在这个例子中,Liftoff 将寻找.hacker.js相对于cwd中声明的文件configFiles

const  MyApp  =  new  Liftoff ( { 

name : 'hacker' ,

configFiles : {

'.hacker' : {

cwd : '.'

}

}

} ) ;

在本例中,Liftoff 将.hackerrc在主目录中查找。

const  MyApp  =  new  Liftoff ( { 

name : 'hacker' ,

configFiles : {

'.hacker' : {

home : {

path : '~' ,

extensions : {

'rc' : null

}

}

}

}

} ) ;

在这个例子中,Liftoff 将在 cwd 中查找,然后在树中查找 .hacker.js 文件。

const MyApp = new Liftoff({

name: 'hacker',

configFiles: {

'.hacker': {

up: {

path: '.',

findUp: true

}

}

}

});

在这个例子中,name被覆盖,键被忽略,所以 Liftoff 寻找.override.js

const  MyApp  =  new  Liftoff ( { 

name : 'hacker' ,

configFiles : {

hacker : {

override : {

path : '.' ,

name : '.override'

}

}

}

} ) ;

在本例中,Liftoff 将使用主目录作为cwd并查找~/.hacker.js.

const  MyApp  =  new  Liftoff( { 

name : 'hacker' ,

configFiles : {

'.hacker' : {

home : {

path : '.' ,

cwd : '~'

}

}

}

} ) ;

prepare(opts, callback(env))

使用提供的选项为您的应用程序准备环境,并使用计算的环境作为第一个参数调用您的回调。可以在将环境用作 的第一个参数之前修改环境execute

带有选项解析的示例配置:

const Liftoff = require('liftoff');

const MyApp = new Liftoff({name:'myapp'});

const argv = require('minimist')(process.argv.slice(2));

const onExecute = function (env, argv) {

// Do post-execute things

};

const onPrepare = function (env) {

console.log('my environment is:', env);

console.log('my liftoff config is:', this);

MyApp.execute(env, onExecute);

};

MyApp.prepare({

cwd: argv.cwd,

configPath: argv.myappfile,

preload: argv.preload,

completion: argv.completion

}, onPrepare);

带有修改环境的示例

const Liftoff = require('liftoff');

const Hacker = new Liftoff({

name: 'hacker',

configFiles: {

'.hacker': {

home: { path: '.', cwd: '~' }

}

}

});

const onExecute = function (env, argv) {

// Do post-execute things

};

const onPrepare = function (env) {

env.configProps = ['home', 'cwd'].map(function(dirname) {

return env.configFiles['.hacker'][dirname]

}).filter(function(filePath) {

return Boolean(filePath);

}).reduce(function(config, filePath) {

return mergeDeep(config, require(filePath));

}, {});

if (env.configProps.hackerfile) {

env.configPath = path.resolve(env.configProps.hackerfile);

env.configBase = path.dirname(env.configPath);

}

Hacker.execute(env, onExecute);

};

Hacker.prepare({}, onPrepare);

opts.cwd

更改此启动的当前工作目录。相对路径是针对 计算的process.cwd()

类型:String

默认:process.cwd()

示例配置:

const argv = require('minimist')(process.argv.slice(2));

MyApp.launch({

cwd: argv.cwd

}, invoke);

匹配 CLI 调用:

myapp --cwd ../

opts.configPath

不要搜索配置,使用提供的配置。注意: Liftoff 将假定当前工作目录是包含配置文件的目录,除非使用cwd.

类型:String

默认:null

示例配置:

var argv = require('minimist')(process.argv.slice(2));

MyApp.launch({

configPath: argv.myappfile

}, invoke);

匹配 CLI 调用:

myapp --myappfile /var/www/project/Myappfile.js

使用cwdconfigPath一起使用的示例:

这些在功能上是相同的:

myapp --myappfile /var/www/project/Myappfile.js

myapp --cwd /var/www/project

这些可以从共享目录运行 myapp,就好像它位于另一个项目中一样:

myapp --myappfile /Users/name/Myappfile.js --cwd /var/www/project1

myapp --myappfile /Users/name/Myappfile.js --cwd /var/www/project2

预加载

在调用启动回调之前尝试从本地工作目录请求的字符串或模块数组。

类型:String|Array

默认:null

示例配置:

var argv = require('minimist')(process.argv.slice(2));

MyApp.launch({

preload: argv.preload

}, invoke);

匹配 CLI 调用:

myapp --preload coffee-script/register

callback(env)

在您的环境准备好后调用的函数。在调用之前修改环境的好地方execute。调用时,this将是您的 Liftoff 实例。该env参数将包含以下键:

  • cwd: 当前工作目录
  • preload:一系列升空尝试预加载的模块
  • configNameSearch: 搜索的配置文件
  • configPath:配置文件的完整路径(如果找到)
  • configBase:配置文件的基本目录(如果找到)
  • modulePath:您的项目所依赖的本地模块的完整路径(如果找到)
  • modulePackage:本地模块的 package.json 的内容(如果找到)
  • configFiles:每个找到的配置文件的文件路径对象(如果找不到,文件路径值将为空)

execute(env, [forcedFlags], callback(env, argv))

基于env给定的启动应用程序的函数。可选地采用 的数组forcedFlags,这将在启动期间强制使用这些节点或 V8 标志重新生成。在应用程序执行后,使用环境和命令行参数(减去节点和 v8 标志)调用您的回调。

例子:

const Liftoff = require('liftoff');

const MyApp = new Liftoff({name:'myapp'});

const onExecute = function (env, argv) {

// Do post-execute things

console.log('my environment is:', env);

console.log('my cli options are:', argv);

console.log('my liftoff config is:', this);

};

const onPrepare = function (env) {

var forcedFlags = ['--trace-deprecation'];

MyApp.execute(env, forcedFlags, onExecute);

};

MyApp.prepare({}, onPrepare);

callback(env, argv)

在您的应用程序执行后调用的函数。调用时,this将是您的 Liftoff 实例,argv将是所有命令行参数(减去节点和 v8 标志),env并将包含以下键:

  • cwd: 当前工作目录
  • preload:一系列升空尝试预加载的模块
  • configNameSearch: 搜索的配置文件
  • configPath:配置文件的完整路径(如果找到)
  • configBase:配置文件的基本目录(如果找到)
  • modulePath:您的项目所依赖的本地模块的完整路径(如果找到)
  • modulePackage:本地模块的 package.json 的内容(如果找到)
  • configFiles:每个找到的配置文件的文件路径对象(如果找不到,文件路径值将为空)

events

on('preload:before', function(name) {})

在预加载模块之前发出。(但仅适用于由 指定的模块 opts.preload)。

var Hacker = new Liftoff({name:'hacker', preload:'coffee-script'});

Hacker.on('preload:before', function (name) {

console.log('Requiring external module: '+name+'...');

});

on('preload:success', function(name, module) {})

当模块被预加载时发出。

var Hacker = new Liftoff({name:'hacker'});

Hacker.on('preload:success', function (name, module) {

console.log('Required external module: '+name+'...');

// automatically register coffee-script extensions

if (name === 'coffee-script') {

module.register();

}

});

on('preload:failure', function(name, err) {})

当请求的模块无法预加载时发出。

var Hacker = new Liftoff({name:'hacker'});

Hacker.on('preload:failure', function (name, err) {

console.log('Unable to load:', name, err);

});

on('loader:success, function(name, module) {})

当加载了与扩展匹配的加载器时发出。

var Hacker = new Liftoff({

name: 'hacker',

extensions: {

'.ts': 'ts-node/register'

}

});

Hacker.on('loader:success', function (name, module) {

console.log('Required external module: '+name+'...');

});

on('loader:failure', function(name, err) {})

当无法加载扩展的加载器时发出。为每个失败的加载器发出一个错误。

var Hacker = new Liftoff({

name: 'hacker',

extensions: {

'.ts': 'ts-node/register'

}

});

Hacker.on('loader:failure', function (name, err) {

console.log('Unable to load:', name, err);

});

on('respawn', function(flags, child) {})

当 Liftoff 重新生成您的进程时发出(当一个 v8flags 被检测到)。

var Hacker = new Liftoff({

name: 'hacker',

v8flags: ['--harmony']

});

Hacker.on('respawn', function (flags, child) {

console.log('Detected node flags:', flags);

console.log('Respawned to PID:', child.pid);

});

此命令将触发事件: hacker --harmony commmand

例子

看看如何 gulp 使用起飞。

对于一个简单的例子,试试 hacker project。

要尝试该示例,请执行以下操作:

  1. 安装示例项目hackernpm install -g hacker
  2. Hackerfile.js用一些任意的 javascript做一个吧。
  3. 在它旁边安装黑客npm install hacker
  4. 运行hacker,而在同一个父文件夹。

项目地址:https://github.com/js-cli/js-liftoff

以上是 node-liftoff 更简单地创建命令行工具 的全部内容, 来源链接: utcz.com/p/233791.html

回到顶部