Commit 98a9abb
Changed files (5)
experimental.d.ts
@@ -0,0 +1,26 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import {ProcessOutput} from './index'
+
+interface Echo {
+ (pieces: TemplateStringsArray, ...args: any[]): Promise<void>
+}
+
+interface Retry {
+ (pieces: TemplateStringsArray, ...args: any[]): Promise<ProcessOutput>
+}
+
+export const echo: Echo
+export const retry: (count: number) => Retry
experimental.mjs
@@ -0,0 +1,44 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import {ProcessOutput} from './index.mjs'
+
+// Retries a command a few times. Will return after the first
+// successful attempt, or will throw after specifies attempts count.
+export const retry = (count = 5) => async (cmd, ...args) => {
+ while (count --> 0) try {
+ return await $(cmd, ...args)
+ } catch (p) {
+ if (count === 0) throw p
+ }
+}
+
+// A console.log() alternative which can take ProcessOutput.
+export const echo = (pieces, ...args) => {
+ if (!Array.isArray(pieces) || pieces.length - 1 !== args.length) {
+ throw new Error('The echo is a template string. Use as echo`...`.')
+ }
+ let msg = pieces[0], i = 0
+ while (i < args.length) {
+ msg += stringify(args[i]) + pieces[++i]
+ }
+ console.log(msg)
+}
+
+function stringify(arg) {
+ if (arg instanceof ProcessOutput) {
+ return arg.toString().replace(/\n$/, '')
+ }
+ return `${arg}`
+}
package.json
@@ -5,7 +5,8 @@
"main": "./index.mjs",
"exports": {
".": "./index.mjs",
- "./globals": "./globals.mjs"
+ "./globals": "./globals.mjs",
+ "./experimental": "./experimental.mjs"
},
"types": "index.d.ts",
"bin": {
README.md
@@ -338,6 +338,33 @@ files (when using `zx` executable).
let {version} = require('./package.json')
```
+### Experimental
+
+The zx also provides a few experimental functions. Please leave a feedback about
+those features in [the discussion](https://github.com/google/zx/discussions/299).
+
+#### `retry()`
+
+Retries a command a few times. Will return after the first
+successful attempt, or will throw after specifies attempts count.
+
+```js
+import {retry} from 'zx/experimental'
+
+let {stdout} = await retry(5)`curl localhost`
+```
+
+#### ``echo`...` ``
+
+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}.`
+```
+
### FAQ
#### Passing env variables
test.mjs
@@ -13,6 +13,7 @@
// limitations under the License.
import {strict as assert} from 'assert'
+import {retry} from './experimental.mjs'
{ // Only stdout is used during command substitution
let hello = await $`echo Error >&2; echo Hello`
@@ -218,6 +219,14 @@ import {strict as assert} from 'assert'
console.log(chalk.greenBright('YAML works'))
}
+{ // Retry works.
+ try {
+ await retry(5)`exit 123`
+ } catch (p) {
+ assert.equal(p.exitCode, 123)
+ }
+}
+
{ // require() is working in ESM
const {name, version} = require('./package.json')
assert(typeof name === 'string')