Commit 5b0a0cd
Changed files (4)
index.d.ts
@@ -38,6 +38,7 @@ export interface ProcessPromise<T> extends Promise<T> {
readonly stdin: Writable
readonly stdout: Readable
readonly stderr: Readable
+ readonly exitCode: Promise<number>
pipe(dest: ProcessPromise<ProcessOutput> | Writable): ProcessPromise<ProcessOutput>
}
index.mjs
@@ -53,7 +53,7 @@ export function $(pieces, ...args) {
code, stdout, stderr, combined,
message: `${stderr || '\n'} at ${__from}`
});
- (code === 0 ? resolve : reject)(output)
+ (code === 0 || promise._nothrow ? resolve : reject)(output)
})
})
})
@@ -136,9 +136,15 @@ export async function fetch(url, init) {
export const sleep = promisify(setTimeout)
+export function nothrow(promise) {
+ promise._nothrow = true
+ return promise
+}
+
export class ProcessPromise extends Promise {
child = undefined
_stop = () => void 0
+ _nothrow = false
get stdin() {
return this.child.stdin
@@ -152,6 +158,12 @@ export class ProcessPromise extends Promise {
return this.child.stderr
}
+ get exitCode() {
+ return this
+ .then(p => p.exitCode)
+ .catch(p => p.exitCode)
+ }
+
pipe(dest) {
if (typeof dest === 'string') {
throw new Error('The pipe() method does not take strings. Forgot $?')
@@ -217,6 +229,7 @@ Object.assign(global, {
chalk,
fetch,
fs: {...fs, createWriteStream, createReadStream},
+ nothrow,
os,
question,
sleep,
README.md
@@ -95,6 +95,7 @@ class ProcessPromise<T> extends Promise<T> {
readonly stdin: Writable
readonly stdout: Readable
readonly stderr: Readable
+ readonly exitCode: Promise<number>
pipe(dest): ProcessPromise<T>
}
```
@@ -172,6 +173,34 @@ Usage:
await sleep(1000)
```
+### `nothrow()`
+
+Changes behavior of `$` to not throw an exception on non-zero exit codes.
+
+```ts
+function nothrow(p: ProcessPromise<ProcessOutput>): ProcessPromise<ProcessOutput>
+```
+
+Usage:
+
+```js
+await nothrow($`grep something from-file`)
+
+// Inside a pipe():
+
+await $`find ./examples -type f -print0`
+ .pipe(nothrow($`xargs -0 grep something`))
+ .pipe($`wc -l`)
+```
+
+If only the `exitCode` is needed, you can use the next code instead:
+
+```js
+if (await $`[[ -d path ]]`.exitCode == 0) {...}
+// Equivalent of:
+if ((await nothrow($`[[ -d path ]]`)).exitCode == 0) {...}
+```
+
### `chalk` package
The [chalk](https://www.npmjs.com/package/chalk) package is available without
@@ -289,8 +318,7 @@ zx examples/index.md
### TypeScript scripts
-The `zx` can compile `.ts` scripts to `.mjs` by running `tsc` (should be
-installed on local machine).
+The `zx` can compile `.ts` scripts to `.mjs` and execute them.
```bash
zx examples/typescript.ts
test.mjs
@@ -119,6 +119,16 @@ import {strict as assert} from 'assert'
console.log('☝️ Error above is expected')
}
+{ // ProcessOutput::exitCode doesn't throw
+ assert(await $`grep qwerty README.md`.exitCode !== 0)
+ assert(await $`[[ -f ${__filename} ]]`.exitCode === 0)
+}
+
+{ // nothrow() doesn't throw
+ let {exitCode} = await nothrow($`exit 42`)
+ assert(exitCode === 42)
+}
+
{ // require() is working in ESM
const {name, version} = require('./package.json')
assert(typeof name === 'string')