node-liftoff 更简单地创建命令行工具
它是什么?
假设您正在编写 CLI 工具。我们称之为 hacker。您想使用 Hackerfile
. 这是节点,因此您 hacker
为使用它的每个项目在本地安装。但是,为了 hacker
在 PATH 中获取命令,您还需要全局安装它。
现在,当您运行 hacker
时 ,您希望使用 Hackerfile
当前目录中的配置它的功能,并希望它使用工具的本地安装来执行。此外,如果该 hacker
命令足够智能,可以遍历您的文件夹,直到找到 Hackerfile
- 对于您不在项目根目录中的那些时间,那就太好了。哎呀,您甚至可能希望 hacker
通过手动指定工作目录从项目外部的文件夹启动。Liftoff 为您管理这些。
所以,一切都很好。现在,你可以找到你的本地 hacker
和 Hackerfile
轻松。不幸的是,事实证明您已经编写 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
extensions
要name
在查找期间附加到的扩展名。另见: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
使用cwd
和configPath
一起使用的示例:
这些在功能上是相同的:
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。
要尝试该示例,请执行以下操作:
- 安装示例项目
hacker
用npm install -g hacker
。 Hackerfile.js
用一些任意的 javascript做一个吧。- 在它旁边安装黑客
npm install hacker
。 - 运行
hacker
,而在同一个父文件夹。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: 为什么 TCP 建立连接需要三次握手
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论