Commit 81a3940

Anton Golub <antongolub@antongolub.com>
2025-01-30 22:01:13
docs: describe `$.defaults` and shell setup helpers, mention asyncIterator, align headers formatting (#1091)
1 parent a94559d
docs/api.md
@@ -1,6 +1,6 @@
 # API Reference
 
-## $.sync 
+## `$.sync`
 Zx provides both synchronous and asynchronous command executions, returns [`ProcessOutput`](./process-output) or [`ProcessPromise`](./process-promise) respectively.
 
 ```js
@@ -8,7 +8,7 @@ const list = await $`ls -la`
 const dir = $.sync`pwd`
 ```
 
-## $({...})
+## `$({...})`
 
 `$` object holds the default zx [configuration](./configuration), which is used for all execution. To specify a custom preset use `$` as factory:
 
@@ -36,7 +36,7 @@ const $3 = $({ sync: true })({ nothrow: true })
 assert.equal($3`exit 3`.exitCode, 3)
 ```
 
-### $({input})
+### `$({input})`
 
 The input option passes the specified `stdin` to the command.
 
@@ -48,7 +48,7 @@ const p4 = $({ input: p3 })`cat`
 const p5 = $({ input: await p3 })`cat`
 ```
 
-### $({signal})
+### `$({signal})`
 
 The signal option makes the process abortable.
 
@@ -59,7 +59,7 @@ const p = $({ signal })`sleep 9999`
 setTimeout(() => signal.abort('reason'), 1000)
 ```
 
-### $({timeout})
+### `$({timeout})`
 
 The timeout option makes the process autokillable after the specified delay.
 
@@ -97,8 +97,9 @@ interface Options {
   halt:           boolean
 }
 ```
+See also [Configuration](./configuration).
 
-## cd()
+## `cd()`
 
 Changes the current working directory.
 
@@ -116,7 +117,7 @@ cd(await $`mktemp -d`)
 
 > ⚠️ `cd` invokes `process.chdir()` internally, so it does affect the global context. To keep `process.cwd()` in sync with separate `$` calls enable [syncProcessCwd()](#syncprocesscwd) hook.
 
-## fetch()
+## `fetch()`
 
 A wrapper around the [node-fetch-native](https://www.npmjs.com/package/node-fetch-native)
 package.
@@ -125,7 +126,7 @@ package.
 const resp = await fetch('https://medv.io')
 ```
 
-## question()
+## `question()`
 
 A wrapper around the [readline](https://nodejs.org/api/readline.html) package.
 
@@ -133,7 +134,7 @@ A wrapper around the [readline](https://nodejs.org/api/readline.html) package.
 const bear = await question('What kind of bear is best? ')
 ```
 
-## sleep()
+## `sleep()`
 
 A wrapper around the `setTimeout` function.
 
@@ -141,7 +142,7 @@ A wrapper around the `setTimeout` function.
 await sleep(1000)
 ```
 
-## echo()
+## `echo()`
 
 A `console.log()` alternative which can take [ProcessOutput](#processoutput).
 
@@ -153,7 +154,7 @@ echo`Current branch is ${branch}.`
 echo('Current branch is', branch)
 ```
 
-## stdin()
+## `stdin()`
 
 Returns the stdin as a string.
 
@@ -161,7 +162,7 @@ Returns the stdin as a string.
 const content = JSON.parse(await stdin())
 ```
 
-## within()
+## `within()`
 
 Creates a new async context.
 
@@ -195,7 +196,7 @@ const version = await within(async () => {
 echo(version) // => v16.20.0
 ```
 
-## syncProcessCwd()
+## `syncProcessCwd()`
 
 Keeps the `process.cwd()` in sync with the internal `$` current working directory if it is changed via [cd()](#cd).
 
@@ -208,7 +209,7 @@ syncProcessCwd(false) // pass false to disable the hook
 
 > This feature is disabled by default because of performance overhead.
 
-## retry()
+## `retry()`
 
 Retries a callback for a few times. Will return after the first
 successful attempt, or will throw after specifies attempts count.
@@ -223,7 +224,7 @@ const p = await retry(20, '1s', () => $`curl https://medv.io`)
 const p = await retry(30, expBackoff(), () => $`curl https://medv.io`)
 ```
 
-## spinner()
+## `spinner()`
 
 Starts a simple CLI spinner.
 
@@ -236,7 +237,7 @@ await spinner('working...', () => $`sleep 99`)
 
 And it's disabled for `CI` by default.
 
-## glob()
+## `glob()`
 
 The [globby](https://github.com/sindresorhus/globby) package.
 
@@ -244,7 +245,7 @@ The [globby](https://github.com/sindresorhus/globby) package.
 const packages = await glob(['package.json', 'packages/*/package.json'])
 ```
 
-## which()
+## `which()`
 
 The [which](https://github.com/npm/node-which) package.
 
@@ -258,7 +259,7 @@ If nothrow option is used, returns null if not found.
 const pathOrNull = await which('node', { nothrow: true })
 ```
 
-## ps()
+## `ps`
 
 The [@webpod/ps](https://github.com/webpod/ps) package to provide a cross-platform way to list processes.
 
@@ -269,7 +270,7 @@ const children = await ps.tree({ pid: 123 })
 const fulltree = await ps.tree({ pid: 123, recursive: true })
 ```
 
-## kill()
+## `kill()`
 
 A process killer.
 
@@ -278,7 +279,7 @@ await kill(123)
 await kill(123, 'SIGKILL')
 ```
 
-## tmpdir()
+## `tmpdir()`
 
 Creates a temporary directory.
 
@@ -287,7 +288,7 @@ t1 = tmpdir()       // /os/based/tmp/zx-1ra1iofojgg/
 t2 = tmpdir('foo')  // /os/based/tmp/zx-1ra1iofojgg/foo/
 ```
 
-## tmpfile()
+## `tmpfile()`
 
 Temp file factory.
 
@@ -298,7 +299,7 @@ f3 = tmpfile('f3.txt', 'string or buffer')
 f4 = tmpfile('f4.sh', 'echo "foo"', 0o744) // executable
 ```
 
-## minimist
+## `minimist`
 
 The [minimist](https://www.npmjs.com/package/minimist) package.
 
@@ -306,7 +307,7 @@ The [minimist](https://www.npmjs.com/package/minimist) package.
 const argv = minimist(process.argv.slice(2), {})
 ```
 
-## argv
+## `argv`
 
 A minimist-parsed version of the `process.argv` as `argv`.
 
@@ -330,7 +331,7 @@ const myCustomArgv = minimist(process.argv.slice(2), {
 })
 ```
 
-## chalk
+## `chalk`
 
 The [chalk](https://www.npmjs.com/package/chalk) package.
 
@@ -338,7 +339,7 @@ The [chalk](https://www.npmjs.com/package/chalk) package.
 console.log(chalk.blue('Hello world!'))
 ```
 
-## fs
+## `fs`
 
 The [fs-extra](https://www.npmjs.com/package/fs-extra) package.
 
@@ -346,7 +347,7 @@ The [fs-extra](https://www.npmjs.com/package/fs-extra) package.
 const {version} = await fs.readJson('./package.json')
 ```
 
-## os
+## `os`
 
 The [os](https://nodejs.org/api/os.html) package.
 
@@ -354,7 +355,7 @@ The [os](https://nodejs.org/api/os.html) package.
 await $`cd ${os.homedir()} && mkdir example`
 ```
 
-## path
+## `path`
 
 The [path](https://nodejs.org/api/path.html) package.
 
@@ -362,7 +363,7 @@ The [path](https://nodejs.org/api/path.html) package.
 await $`mkdir ${path.join(basedir, 'output')}`
 ```
 
-## yaml
+## `yaml`
 
 The [yaml](https://www.npmjs.com/package/yaml) package.
 
@@ -370,7 +371,8 @@ The [yaml](https://www.npmjs.com/package/yaml) package.
 console.log(YAML.parse('foo: bar').foo)
 ```
 
-## dotenv
+## `dotenv`
+
 The [envapi](https://www.npmjs.com/package/envapi) package.  
 An API to interact with environment vars in [dotenv](https://www.npmjs.com/package/dotenv) format.
 
@@ -388,3 +390,43 @@ await $({ env })`echo $FOO`.stdout // BAR
 dotenv.config('.env')
 process.env.FOO // BAR
 ```
+
+## `quote()`
+
+Default bash quoting function.
+
+```js
+quote("$FOO") // "$'$FOO'"
+```
+
+## `quotePowerShell()`
+
+PowerShell specific quoting.
+
+```js
+quotePowerShell("$FOO") // "'$FOO'"
+```
+
+## `useBash()`
+
+Enables bash preset: sets `$.shell` to `bash` and `$.quote` to `quote`.
+
+```js
+useBash()
+```
+
+## `usePowerShell()`
+
+Switches to PowerShell. Applies the `quotePowerShell` for quoting.
+
+```js
+usePowerShell()
+```
+
+## `usePwsh()`
+
+Sets pwsh (PowerShell v7+) as `$.shell` default.
+
+```js
+usePwsh()
+```
docs/cli.md
@@ -11,7 +11,8 @@ zx script.mjs
 If script does not have a file extension (like `.git/hooks/pre-commit`), zx
 assumes that it is
 an [ESM](https://nodejs.org/api/modules.html#modules_module_createrequire_filename)
-module.
+module unless the `--ext` option is specified.
+
 
 ```bash
 zx docs/markdown.md
@@ -36,7 +37,7 @@ await $`pwd`
 EOF
 ```
 
-## --eval
+## `--eval`
 
 Evaluate the following argument as a script.
 
@@ -44,10 +45,10 @@ Evaluate the following argument as a script.
 cat package.json | zx --eval 'const v = JSON.parse(await stdin()).version; echo(v)'
 ```
 
-## --repl
+## `--repl`
 Starts zx in [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop) mode.
 
-## --install
+## `--install`
 
 ```js
 // script.mjs:
@@ -70,7 +71,7 @@ the import.
 import sh from 'tinysh' // @^1
 ```
 
-## --registry
+## `--registry`
 
 By default, `zx` uses `https://registry.npmjs.org` as a registry. Customize if needed.
 
@@ -78,15 +79,15 @@ By default, `zx` uses `https://registry.npmjs.org` as a registry. Customize if n
 zx --registry=https://registry.yarnpkg.com script.mjs
 ```
 
-## --quiet
+## `--quiet`
 
 Suppress any outputs.
 
-## --verbose
+## `--verbose`
 
 Enable verbose mode.
 
-## --shell
+## `--shell`
 
 Specify a custom shell binary.
 
@@ -94,7 +95,7 @@ Specify a custom shell binary.
 zx --shell=/bin/bash script.mjs
 ```
 
-## --prefer-local, -l
+## `--prefer-local, -l`
 
 Prefer locally installed packages bins.
 
@@ -102,7 +103,7 @@ Prefer locally installed packages bins.
 zx --shell=/bin/bash script.mjs
 ```
 
-## --prefix & --postfix
+## `--prefix & --postfix`
 
 Attach a command to the beginning or the end of every command.
 
@@ -110,7 +111,7 @@ Attach a command to the beginning or the end of every command.
 zx --prefix='echo foo;' --postfix='; echo bar' script.mjs
 ```
 
-## --cwd
+## `--cwd`
 
 Set the current working directory.
 
@@ -118,7 +119,7 @@ Set the current working directory.
 zx --cwd=/foo/bar script.mjs
 ```
 
-## --env
+## `--env`
 Specify an env file.
 
 ```bash
@@ -128,15 +129,15 @@ zx --env=/path/to/some.env script.mjs
 When `cwd` option is specified, it will be used as base path:  
 `--cwd='/foo/bar' --env='../.env'` → `/foo/.env`
 
-## --ext
+## `--ext`
 
 Override the default (temp) script extension. Default is `.mjs`.
 
-## --version, -v
+## `--version, -v`
 
 Print the current `zx` version.
 
-## --help, -h
+## `--help, -h`
 
 Print help notes.
 
@@ -156,13 +157,13 @@ steps:
       ZX_SHELL: '/bin/bash'
 ```
 
-## __filename & __dirname
+## `__filename & __dirname`
 
 In [ESM](https://nodejs.org/api/esm.html) modules, Node.js does not provide
 `__filename` and `__dirname` globals. As such globals are really handy in scripts,
 zx provides these for use in `.mjs` files (when using the `zx` executable).
 
-## require()
+## `require()`
 
 In [ESM](https://nodejs.org/api/modules.html#modules_module_createrequire_filename)
 modules, the `require()` function is not defined.
docs/configuration.md
@@ -1,6 +1,6 @@
 # Configuration
 
-## $.shell
+## `$.shell`
 
 Specifies what shell is used. Default is `which bash`.
 
@@ -10,13 +10,13 @@ $.shell = '/usr/bin/bash'
 
 Or use a CLI argument: `--shell=/bin/bash`
 
-## $.spawn
+## `$.spawn`
 
 Specifies a `spawn` api. Defaults to `require('child_process').spawn`.
 
 To override a sync API implementation, set `$.spawnSync` correspondingly.
 
-## $.prefix
+## `$.prefix`
 
 Specifies the command that will be prefixed to all commands run.
 
@@ -24,7 +24,7 @@ Default is `set -euo pipefail;`.
 
 Or use a CLI argument: `--prefix='set -e;'`
 
-## $.postfix
+## `$.postfix`
 
 Like a `$.prefix`, but for the end of the command.
 
@@ -32,7 +32,7 @@ Like a `$.prefix`, but for the end of the command.
 $.postfix = '; exit $LastExitCode' // for PowerShell compatibility
 ```
 
-## $.preferLocal
+## `$.preferLocal`
 
 Specifies whether to prefer `node_modules/.bin` located binaries over globally system installed ones.
 
@@ -49,12 +49,12 @@ $.preferLocal = '/some/to/bin'
 $.preferLocal = ['/path/to/bin', '/another/path/bin']
 ```
 
-## $.quote
+## `$.quote`
 
 Specifies a function for escaping special characters during
 command substitution.
 
-## $.verbose
+## `$.verbose`
 
 Specifies verbosity. Default is `false`.
 
@@ -63,26 +63,26 @@ outputs.
 
 Or use the CLI argument: `--verbose` to set `true`.
 
-## $.quiet
+## `$.quiet`
 
 Suppresses all output. Default is `false`.
 
 Via CLI argument: `--quiet` sets `$.quiet = true`.
 
-## $.env
+## `$.env`
 
 Specifies an environment variables map.
 
 Defaults to `process.env`.
 
-## $.cwd
+## `$.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
+## `$.log`
 
 Specifies a [logging function](src/core.ts).
 
@@ -101,7 +101,7 @@ $.log = (entry: LogEntry) => {
 }
 ```
 
-## $.timeout
+## `$.timeout`
 
 Specifies a timeout for the command execution.
 
@@ -111,3 +111,30 @@ $.timeoutSignal= 'SIGKILL'
 
 await $`sleep 999`
 ```
+
+## `$.defaults`
+
+Holds the default configuration values. They will be used if the corresponding
+`$` options are not specified.
+
+```ts
+$.defaults = {
+  cwd:            process.cwd(),
+  env:            process.env,
+  verbose:        false,
+  quiet:          false,
+  sync:           false,
+  shell:          true,
+  prefix:         'set -euo pipefail;',   // for bash
+  postfix:        '; exit $LastExitCode', // for powershell
+  nothrow:        false,
+  stdio:          'pipe', // equivalent to ['pipe', 'pipe', 'pipe']
+  detached:       false,
+  preferLocal:    false,
+  spawn:          childProcess.spawn,
+  spawnSync:      childProcess.spawnSync,
+  log:            $.log,
+  killSignal:     'SIGTERM',
+  timeoutSignal:  'SIGTERM'
+}
+```
docs/process-promise.md
@@ -76,6 +76,17 @@ await p.lines()       // ['foo', 'bar']
 await $`echo '{"foo": "bar"}'`.json() // {foo: 'bar'}
 ```
 
+## `[Symbol.asyncIterator]`
+
+Returns an async iterator of the stdout process.
+
+```js
+const p = $`echo "Line1\nLine2\nLine3"`
+for await (const line of p) {
+  console.log()
+}
+```
+
 ## `pipe()`
 
 Redirects the output of the process.
@@ -245,13 +256,18 @@ p.abort('reason')
 ```
 
 ## `stdio()`
+Specifies a standard input-output for the process.
 
-Specifies a stdio for the process.
+```js
+const h$ = $({halt: true})
+const p1 = h$`read`.stdio('inherit', 'pipe', null).run()
+const p2 = h$`read`.stdio('pipe').run() // sets ['pipe', 'pipe', 'pipe']
+```
 
-Default is `.stdio('inherit', 'pipe', 'pipe')`.
+Keep in mind, `stdio` should be set before the process is started, so the preset syntax might be preferable:
 
 ```js
-const p = $`read`.stdio('pipe')
+await $({stdio: ['pipe', 'pipe', 'pipe']})`read`
 ```
 
 ## `nothrow()`