Comparing version
48
app.js
'use strict' | ||
const onExit = require('signal-exit') | ||
const yargs = require('yargs') | ||
const path = require('path') | ||
@@ -14,3 +13,6 @@ const fs = require('fs') | ||
if (started && !exited) { | ||
// tested, but exit mechanism can't collect coverage | ||
/* istanbul ignore next */ | ||
if (signal) { | ||
/* istanbul ignore next */ | ||
console.error('Abnormal exit:', signal) | ||
@@ -29,4 +31,6 @@ } else { | ||
? nameMatch.test(pkg.bin) | ||
: Object.keys(pkg.bin).some(b => nameMatch.test(b) || nameMatch.test(pkg.bin[b])) | ||
: pkg.bin && Object.keys(pkg.bin).some(b => nameMatch.test(b) || nameMatch.test(pkg.bin[b])) | ||
if (isInPackage) { | ||
/* istanbul ignore next */ | ||
if (global['NO_NOTIFIER']) throw new Error('NO NOTIFIER') | ||
const updateNotifier = require('update-notifier'); | ||
@@ -38,9 +42,41 @@ updateNotifier({pkg: pkg}).notify() | ||
let yargs | ||
let opts | ||
let argv | ||
try { | ||
/* istanbul ignore next */ | ||
if (global['NO_YARGS']) throw new Error('NO YARGS') | ||
yargs = require('yargs') | ||
opts = yargs.argv | ||
argv = opts._ | ||
} catch (_) { | ||
argv = process.argv.slice(2) | ||
opts = {_: argv} | ||
const noYargs = () => { | ||
throw new Error('Argument parsing is not available (could not find yargs), to install run: npm i yargs') | ||
} | ||
// only missing on v4, which has incomplete coverage anyway | ||
/* istanbul ignore next */ | ||
yargs = global.Proxy && new global.Proxy({}, { | ||
getPrototypeOf: noYargs, | ||
setPrototypeOf: noYargs, | ||
isExtensible: noYargs, | ||
preventExtensions: noYargs, | ||
getOwnPropertyDescriptor: noYargs, | ||
defineProperty: noYargs, | ||
has: noYargs, | ||
get: noYargs, | ||
set: noYargs, | ||
deleteProperty: noYargs, | ||
ownKeys: noYargs, | ||
apply: noYargs, | ||
construct: noYargs | ||
}) | ||
} | ||
setImmediate(() => { | ||
const argv = yargs.argv | ||
started = true | ||
try { | ||
const appPromise = entry.apply(null, [argv].concat(argv._)) | ||
const appPromise = entry.apply(null, [opts].concat(argv)) | ||
if (!appPromise || !appPromise.then) { | ||
return onError(new Error('Error: Application entry point' + (entry.name ? ` (${entry.name})` : '') + ' did not return a promise.')) | ||
return onError(new Error('Application entry point' + (entry.name ? ` (${entry.name})` : '') + ' did not return a promise.')) | ||
} | ||
@@ -56,3 +92,3 @@ appPromise.then(() => exited = true, onError) | ||
} else if (err) { | ||
console.error(err && err.stack ? err.stack : err) | ||
console.error((err && err.stack) ? err.stack : err) | ||
} | ||
@@ -59,0 +95,0 @@ process.exit(1) |
{ | ||
"name": "@iarna/cli", | ||
"version": "1.2.0", | ||
"version": "2.0.0", | ||
"description": "Some simple CLI scaffolding for promise returning applications.", | ||
"main": "app.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
"test": "tap --100 test/scenarios.js" | ||
}, | ||
@@ -13,5 +13,3 @@ "keywords": [], | ||
"dependencies": { | ||
"signal-exit": "^3.0.2", | ||
"update-notifier": "^2.2.0", | ||
"yargs": "^8.0.2" | ||
"signal-exit": "^3.0.2" | ||
}, | ||
@@ -21,3 +19,10 @@ "files": [ | ||
], | ||
"devDependencies": {}, | ||
"devDependencies": { | ||
"@perl/qr": "^1.2.0", | ||
"@perl/qx": "^1.0.2", | ||
"glob": "^7.1.2", | ||
"tap": "^12.0.1", | ||
"update-notifier": "^2.2.0", | ||
"yargs": "^8.0.2" | ||
}, | ||
"repository": { | ||
@@ -24,0 +29,0 @@ "type": "git", |
@@ -5,7 +5,33 @@ # @iarna/cli | ||
 | ||
## EXAMPLE | ||
### Without Yargs | ||
If you don't have yargs installed as a dependency then you get arguments | ||
split out but no option parsing: | ||
`example.js` | ||
```js | ||
require('@iarna/cli')(main) | ||
const util = require('util'); | ||
const sleep = util.promisify(setTimeout); | ||
// opts will only contain the _ var, for compatibility with yargs | ||
async function main (opts, arg1, arg2, arg3) { | ||
console.log('Got:', arg1, arg2, arg3) | ||
await sleep(40) | ||
} | ||
``` | ||
### With Yargs | ||
If you do have yargs installed as a dependency you can customize it further | ||
by chaining off the require in the usual yargsish way. | ||
`example.js` | ||
```js | ||
require('@iarna/cli')(main) | ||
.boolean('silent') | ||
@@ -19,2 +45,5 @@ .boolean('exit') | ||
const util = require('util'); | ||
const sleep = util.promisify(setTimeout); | ||
function main (opts, arg1, arg2, arg3) { | ||
@@ -27,4 +56,7 @@ if (!opts.silent) console.error('Starting up!') | ||
if (opts.code50) return Promise.reject(50) | ||
return new Promise(resolve => setTimeout(resolve, 10000)) | ||
return sleep(10000) | ||
} | ||
// alternatively use: | ||
// function main (opts, ...args) { | ||
``` | ||
@@ -70,17 +102,19 @@ | ||
* `yargs` - The wrapper around the main function returns a yargs object, so | ||
you can configure it as usual. The `argv` object is passed in as the | ||
first argument of your entry point function. The rest of your positional | ||
arguments are passed in as the remaining function arguments. | ||
* _exit without resolving warnings_ - If your program finishes without | ||
resolving its promises (like if it crashes hard or you process.exit, or you just don't resolve the promise ) then | ||
we warn about that. | ||
* `update-notifier` - A default update notifier is setup for your app so | ||
users will learn about new versions when you publish them. Your app needs to | ||
have a name, version and bin entry in its `package.json`. (The bin entry | ||
needs to have the script using `@iarna/cli` in it for the update notifier | ||
to trigger.) | ||
* If your entry point function rejects then that's reported with a stack | ||
trace (if the rejected value has `.stack`) else with the rejected value | ||
and your process will exit with an error code. | ||
* If you add `yargs` as a dependency then it will be taken advantage of. | ||
The wrapper around the main function returns a yargs object, so you can | ||
configure it as usual. The `argv` object is passed in as the first | ||
argument of your entry point function. The rest of your positional | ||
arguments are passed in as the remaining function arguments. | ||
* If you add `update-notifier` as a dependency then it will be taken | ||
advantage of. A default update notifier is setup for your app so users | ||
will learn about new versions when you publish them. Your app needs to | ||
have a name, version and bin entry in its `package.json`. (The bin entry | ||
needs to have the script using `@iarna/cli` in it for the update notifier | ||
to trigger.) | ||
@@ -94,5 +128,9 @@ ## WHAT ITS NOT | ||
It's designed to be only be as heavy as it needs to be. It only has one | ||
direct dependency, but it can provide enhanced functionality if you depend on | ||
`yargs` or `update-notifier`. | ||
## USAGE | ||
### require('@iarna/cli')(entryPointFunction) → yargs | ||
### require('@iarna/cli')(entryPointFunction) → [yargs] | ||
@@ -104,2 +142,7 @@ The module itself exports a function that you need to call with the name of | ||
The return value from the call is, if you have `yargs` installed, a `yargs` | ||
object you can use to configure what options your script takes. If you | ||
don't have yargs installed then it's a proxy that throws if you try to do | ||
anything with it. | ||
Your entry point function can be named anything, but it needs to return a | ||
@@ -110,3 +153,9 @@ promise and it takes arguments like this: | ||
The first `opts` argument is `yargs.argv` and the additional arguments are | ||
from `argv._`, so `arg1 === argv._[0]`, `arg2 === argv._[1]` and so on. | ||
If you have `yargs` installed then the `opts` argument is `yargs.argv` | ||
and the additional arguments are from `argv._`, so `arg1 === argv._[0]`, | ||
`arg2 === argv._[1]` and so on. | ||
If you don't have `yargs` installed then `opts` argument is an object with | ||
an `_` property containing all arguments, for compatibility with the `yargs` | ||
mode. As with that mode `arg1 === argv._[0]`, `arg2 === argv._[1]` and so | ||
on. |
No tests
QualityPackage does not have any tests. This is a strong signal of a poorly maintained or low quality package.
Found 1 instance in 1 package
14909
113.66%1
-66.67%5
25%93
63.16%0
-100%155
46.23%6
Infinity%- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed