Commit db0e651
Changed files (2)
docs/pipelines.md → docs/process-promise.md
@@ -1,10 +1,6 @@
-# Pipelines
+# ProcessPromise
-> You can run this markdown file:
->
-> ```
-> zx docs/pipelines.md
-> ```
+## `pipe()`
The `zx` supports Node.js streams and special `pipe()` method can be used to
redirect stdout.
@@ -61,3 +57,47 @@ await $`find ./examples -type f -print0`
.pipe(nothrow($`xargs -0 grep ${'missing' + 'part'}`))
.pipe($`wc -l`)
```
+
+## `nothrow()`
+
+Changes behavior of `$` to not throw an exception on non-zero exit codes.
+
+```ts
+function nothrow<P>(p: P): P
+```
+
+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) {
+ ...
+}
+```
+
+## `withTimeout()`
+
+Runs and sets a timeout for a cmd.
+
+```js
+import {withTimeout} from 'zx/experimental'
+
+await withTimeout(100, 'SIGTERM')`sleep 9999`
+```
README.md
@@ -35,8 +35,8 @@ npm i -g zx
## Goods
-[$](#command-) · [cd()](#cd) · [fetch()](#fetch) · [question()](#question) · [sleep()](#sleep) · [nothrow()](#nothrow) · [quiet()](#quiet) · [within()](#within) ·
-[chalk](#chalk-package) · [fs](#fs-package) · [os](#os-package) · [path](#path-package) · [globby](#globby-package) · [yaml](#yaml-package) · [minimist](#minimist-package) · [which](#which-package) ·
+[$](#command-) · [cd()](#cd) · [fetch()](#fetch) · [question()](#question) · [sleep()](#sleep) · [echo()](#echo) · [stdin()](#stdin) · [within()](#within) ·
+[chalk](#chalk-package) · [fs](#fs-package) · [os](#os-package) · [path](#path-package) · [glob](#globby-package) · [yaml](#yaml-package) · [minimist](#minimist-package) · [which](#which-package) ·
[__filename](#__filename--__dirname) · [__dirname](#__filename--__dirname) · [require()](#require)
## Documentation
@@ -74,7 +74,7 @@ import 'zx/globals'
### ``$`command` ``
Executes a given string using the `spawn` function from the
-`child_process` package and returns `ProcessPromise<ProcessOutput>`.
+`child_process` package and returns `ProcessPromise`.
Everything passed through `${...}` will be automatically escaped and quoted.
@@ -112,23 +112,17 @@ try {
### `ProcessPromise`
```ts
-class ProcessPromise<T> extends Promise<T> {
- readonly stdin: Writable
- readonly stdout: Readable
- readonly stderr: Readable
- readonly exitCode: Promise<number>
- pipe(dest): ProcessPromise<T>
+class ProcessPromise extends Promise<ProcessOutput> {
+ stdin: Writable
+ stdout: Readable
+ stderr: Readable
+ exitCode: Promise<number>
+ pipe(): ProcessPromise
kill(signal = 'SIGTERM'): Promise<void>
}
```
-The `pipe()` method can be used to redirect stdout:
-
-```js
-await $`cat file.txt`.pipe(process.stdout)
-```
-
-Read more about [pipelines](docs/pipelines.md).
+Read more about the [ProcessPromise](docs/process-promise.md).
### `ProcessOutput`
@@ -136,8 +130,8 @@ Read more about [pipelines](docs/pipelines.md).
class ProcessOutput {
readonly stdout: string
readonly stderr: string
+ readonly signal: string
readonly exitCode: number
- readonly signal: 'SIGTERM' | 'SIGKILL' | ...
toString(): string
}
```
@@ -150,7 +144,7 @@ Changes the current working directory.
```js
cd('/tmp')
-await $`pwd` // outputs /tmp
+await $`pwd` // => /tmp
```
### `fetch()`
@@ -158,30 +152,15 @@ await $`pwd` // outputs /tmp
A wrapper around the [node-fetch](https://www.npmjs.com/package/node-fetch) package.
```js
-let resp = await fetch('https://wttr.in')
-if (resp.ok) {
- console.log(await resp.text())
-}
+let resp = await fetch('https://medv.io/*')
```
### `question()`
A wrapper around the [readline](https://nodejs.org/api/readline.html) package.
-Usage:
-
```js
let bear = await question('What kind of bear is best? ')
-let token = await question('Choose env variable: ', {
- choices: Object.keys(process.env)
-})
-```
-
-In second argument, array of choices for Tab autocompletion can be specified.
-
-```ts
-function question(query?: string, options?: QuestionOptions): Promise<string>
-type QuestionOptions = { choices: string[] }
```
### `sleep()`
@@ -192,96 +171,50 @@ A wrapper around the `setTimeout` function.
await sleep(1000)
```
-### `nothrow()`
-
-Changes behavior of `$` to not throw an exception on non-zero exit codes.
-
-```ts
-function nothrow<P>(p: P): P
-```
-
-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`)
-```
+### `echo()`
-If only the `exitCode` is needed, you can use the next code instead:
+A `console.log()` alternative which can take [ProcessOutput](#processoutput).
```js
-if (await $`[[ -d path ]]`.exitCode == 0) {
- ...
-}
-
-// Equivalent of:
+let branch = await $`git branch --show-current`
-if ((await nothrow($`[[ -d path ]]`)).exitCode == 0) {
- ...
-}
+echo`Current branch is ${branch}.`
+// or
+echo('Current branch is', branch)
```
-### `quiet()`
+### `stdin()`
-Changes behavior of `$` to disable verbose output.
+Returns the stdin as a string.
-```ts
-function quiet<P>(p: P): P
```
-
-Usage:
-
-```js
-await quiet($`grep something from-file`)
-// Command and output will not be displayed.
+let content = JSON.parse(await stdin())
```
### `within()`
Creates a new async context.
-```ts
-function within(callback): void
-```
-
-Usage:
-
```js
-$.verbose = true
await $`pwd` // => /home/path
within(async () => {
- $.verbose = false
cd('/tmp')
setTimeout(async () => {
await $`pwd` // => /tmp
- assert($.verbose == false)
}, 1000)
})
await $`pwd` // => /home/path
-assert($.verbose == true)
```
-Building profiled commands stack:
-
```js
-const nodev = async (v) => within(async () => {
- $.verbose = false
+let version = await within(async () => {
$.prefix += 'export NVM_DIR=$HOME/.nvm; source $NVM_DIR/nvm.sh; '
-
- await $`nvm use ${v}`
-
- return $`node -v`.then(r => r.stdout.trim().slice(1)) // 'v18.0.0\n' → '18.0.0'
+ await $`nvm use 16`
+ return $`node -v`
})
-
-await nodev(18) // '18.0.0'
````
## Packages
@@ -301,7 +234,7 @@ console.log(chalk.blue('Hello world!'))
The [fs-extra](https://www.npmjs.com/package/fs-extra) package.
```js
-let content = await fs.readFile('./package.json')
+let {version} = await fs.readJson('./package.json')
```
### `os` package
@@ -325,15 +258,7 @@ await $`mkdir ${path.join(basedir, 'output')}`
The [globby](https://github.com/sindresorhus/globby) package.
```js
-let packages = await globby(['package.json', 'packages/*/package.json'])
-
-let pictures = globby.globbySync('content/*.(jpg|png)')
-```
-
-Also, globby available via the `glob` shortcut:
-
-```js
-await $`svgo ${await glob('*.svg')}`
+let packages = await glob(['package.json', 'packages/*/package.json'])
```
### `yaml` package
@@ -346,9 +271,12 @@ console.log(YAML.parse('foo: bar').foo)
### `minimist` package
-The [minimist](https://www.npmjs.com/package/minimist) package.
+The [minimist](https://www.npmjs.com/package/minimist) package available
+as global const `argv`.
-Available as global const `argv`.
+```js
+if( argv.someFlag ){ echo('yes') }
+```
### `which` package
@@ -356,8 +284,6 @@ The [which](https://github.com/npm/node-which) package.
```js
let node = await which('node')
-
-let node = which.sync('node')
```
## Configuration
@@ -376,11 +302,6 @@ Or use a CLI argument: `--shell=/bin/bash`
Specifies a `spawn` api. Defaults to `require('child_process').spawn`.
-### `$.maxBuffer`
-
-Specifies the largest number of bytes allowed on stdout or stderr.
-Defaults to `200 * 1024 * 1024` (200 MiB).
-
### `$.prefix`
Specifies the command that will be prefixed to all commands run.
@@ -405,7 +326,20 @@ Or use a CLI argument `--quiet` to set `$.verbose = false`.
### `$.env`
-Specifies env map. Defaults to `process.env`.
+Specifies an environment variables map.
+
+Defaults to `process.env`.
+
+### `$.cwd`
+
+Specifies a current working directory of all processes created with the `$`.
+
+The [cd()](#cd) func changes only `process.cwd()` and if no `$.cwd` specified,
+all `$` processes use `process.cwd()` by default (same as `spawn` behavior).
+
+### `$.log`
+
+Specifies a [logging function](src/log.ts).
## Polyfills
@@ -434,52 +368,32 @@ To enable new features via CLI pass `--experimental` flag.
### `retry()`
-Retries a command a few times. Will return after the first
+Retries a callback for a few times. Will return after the first
successful attempt, or will throw after specifies attempts count.
```js
-import {retry} from 'zx/experimental'
+import { retry, expBackoff } from 'zx/experimental'
-let {stdout} = await retry(5)`curl localhost`
+let p = await retry(10, () => $`curl https://medv.io`)
-// with a specified delay between attempts
-let {stdout} = await retry(3, 500)`npm whoami`
-```
-
-### `echo()`
+// With a specified delay between attempts.
+let p = await retry(20, '1s', () => $`curl https://medv.io`)
-A `console.log()` alternative which can take [ProcessOutput](#processoutput).
-
-```js
-import {echo} from 'zx/experimental'
-
-let branch = await $`git branch --show-current`
-
-echo`Current branch is ${branch}.`
-// or
-echo('Current branch is', branch)
+// With an exponential backoff.
+let p = await retry(30, expBackoff(), () => $`curl https://medv.io`)
```
-### `startSpinner()`
+### `spinner()`
-Starts a simple CLI spinner, and returns `stop()` function.
+Starts a simple CLI spinner.
```js
-import {startSpinner} from 'zx/experimental'
-
-let stop = startSpinner()
-await $`long-running command`
-stop()
-```
+import { spinner } from 'zx/experimental'
-### `withTimeout()`
-
-Runs and sets a timeout for a cmd.
-
-```js
-import {withTimeout} from 'zx/experimental'
+await spinner(() => $`long-running command`)
-await withTimeout(100, 'SIGTERM')`sleep 9999`
+// With a message.
+await spinner('working...', () => $`sleep 99`)
```
## FAQ
@@ -539,31 +453,9 @@ void async function () {
}()
```
-Use [ts-node](https://github.com/TypeStrong/ts-node#native-ecmascript-modules) as
-a esm node [loader](https://nodejs.org/api/esm.html#esm_experimental_loaders).
-
-```bash
-node --loader ts-node/esm script.ts
-```
-
-You must set [`"type": "module"`](https://nodejs.org/api/packages.html#packages_type)
-in `package.json` and [`"module": "ESNext"`](https://www.typescriptlang.org/tsconfig/#module)
-in `tsconfig.json`.
-
-```json
-{
- "type": "module"
-}
-```
-
-```json
-{
- "compilerOptions": {
- "module": "ESNext"
- }
-}
-```
-
+Set [`"type": "module"`](https://nodejs.org/api/packages.html#packages_type)
+in **package.json** and [`"module": "ESNext"`](https://www.typescriptlang.org/tsconfig/#module)
+in **tsconfig.json**.
### Executing remote scripts
@@ -584,7 +476,15 @@ await $`pwd`
EOF
```
-### Attaching .bash_profile/.zshrc
+### Executing scripts via --eval
+
+Evaluate the following argument as a script.
+
+```bash
+cat package.json | zx --eval 'let v = JSON.parse(await stdin()).version; echo(v)'
+```
+
+### Attaching a profile
By default `child_process` does not include aliases and bash functions.
But you are still able to do it by hand. Just attach necessary directives to `$.prefix`.