Skip to content

Update dependency zx to v8 #2829

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Conversation

elastic-renovate-prod[bot]
Copy link
Contributor

This PR contains the following updates:

Package Type Update Change
zx (source) devDependencies major 7.2.3 -> 8.5.4

Release Notes

google/zx (zx)

v8.5.4: — Pipe Dreamer

Compare Source

v8.5.3: — Trap Master

Compare Source

  • Another portion of JSR related improvements #​1193 #​1192
  • Goods refactoring #​1195
    • Fixes expBackoff implementation
    • Sets $.log.output as default spinner() output
    • Makes configurable question() I/O
  • Added Graaljs compatability test #​1194
  • Docs improvements, usage examples updates #​1198

v8.5.2: — Threaded Perfection

Compare Source

v8.5.0: — Flow Splitter

Compare Source

In this release we're significantly expanding the zx setup capabilities.

zx@lite

Just core functions without extras, ~7x smaller than the full version.
#​1131

npm i zx@lite
npm i zx@8.5.0-lite

Detailed comparison: zx/versions

import { $ } from 'zx'
await $`echo foo`

Channels

We have completely reforged the distribution flow. Now zx is available in multiple formats:

### npm pkg from registry.npmjs.org
npm i zx        

### install directly from the GH
npm i google/zx 

### from GH the npm registry
npm i --registry=https://npm.pkg.github.com @​google/zx

### fetch from the JSR
### https://jsr.io/docs/using-packages

### @​webpod is temporary JSR scope until @​google/zx becomes ready, we'll migrate later
npx jsr add @​webpod/zx
deno add jsr:@​webpod/zx

### homebrew formula
### https://github.com/Homebrew/homebrew-core/blob/master/Formula/z/zx.rb
brew install zx

#​1141...
#​1157

Docker

If you'd prefer to run zx in a container, you can pull the image from the GH docker registry.
node:22-alpine is used as a base. #​1142 #​1145

docker pull ghcr.io/google/zx:8.5.0
docker run -t ghcr.io/google/zx:8.5.0 -e="await \$({verbose: true})\`echo foo\`"
docker run -t -i -v ./:/script ghcr.io/google/zx:8.5.0 script/t.js

Chores

  • Introduced fetch pipe helper to bypass string size limits #​1130 #​977
const p1 = fetch('https://example.com').pipe($`cat`)
const p2 = fetch('https://example.com').pipe`cat`
import { glob } from 'zx'
const packages = glob.sync(['package.json', 'packages/*/package.json'])
ZX_REGISTRY='https://custom-registry.example.com' zx script.js

v8.4.2

Compare Source

v8.4.1: – Rusty Elbow

Compare Source

Logger enhancements are arriving in this release. #​1119 #​1122 #​1123 #​1125

  • You can customize the output by defining your own formatters for each log entry kind.
$.log.formatters = {
  cmd: (entry: LogEntry) => `CMD: ${entry.cmd}`,
  fetch: (entry: LogEntry) => `FETCH: ${entry.url}`
  //...
}
  • Cmd highlighter now should properly detect bins and arguments. If still not, please report it in #​1122
  • Switched to TS 5.8 #​1120
  • Applied zizmor to check GHA workflows #​1126
  • Prettier is now enabled as a pre-commit hook #​1118

v8.4.0: – Drip Detective

Compare Source

Try the new batch of enhancements: npm i zx@8.4.0 https://www.npmjs.com/package/zx/v/8.4.0

Changes

  • The CLI option --prefer-local now allows linking both external binaries and packages #​1116 #​1117
const cwd = tmpdir()
const external = tmpdir()
await fs.outputJson(path.join(external, 'node_modules/a/package.json'), {
  name: 'a',
  version: '1.0.0',
  type: 'module',
  exports: './index.js',
})
await fs.outputFile(
  path.join(external, 'node_modules/a/index.js'),
  `
export const a = 'AAA'
`
)
const script = `
import {a} from 'a'
console.log(a);
`
const out = await $`zx --cwd=${cwd} --prefer-local=${external} --test <<< ${script}`
assert.equal(out.stdout, 'AAA\n')
  • The quote has been slightly changed for a conner case, when zx literal gets an array.
    #​999 #​1113
const p = $({prefix: '', postfix: ''})`echo ${[1, '', '*', '2']}`

// before
p.cmd //  `echo 1  $'*' 2`) 

// after
p.cmd //  `echo 1 $'' $'*' 2`) 
zx script.zx           # Unknown file extension "\.zx"
zx --ext=mjs script.zx # OK
const err = new Error('BrokenSpawn')
const o = await $({
  nothrow: true,
  spawn() {
    throw err
  },
})`echo foo`
o.ok       // false
o.exitCode // null
o.message  // BrokenSpawn...
o.cause    // err

v8.3.2: – Clogged Drain

Compare Source

Restrics unsafe vals usage on dotenv.stringify #​1093 #​1094

v8.3.1: – Perfect Seal

Compare Source

The release essence: introduced full-featured .env support #​461#​1060 #​1052 #​1043 #​1037 #​1032 #​1030 #​1022

API

envapi is a tiny 100 LOC dotenv-inspired parser and serializer that we've integrated into zx.

import { dotenv, fs } from 'zx'

// parse
const env = dotenv.parse('A=A\nFOO=BAR') // { A: 'A', FOO: 'BAR' }

// serialize
const raw = dotenv.stringify(env) // A=A\nFOO=BAR
await fs.writeFile('.env', raw)

// load
dotenv.load('.env') // { A: 'A', FOO: 'BAR' }

// update the process.env
dotenv.config('.env')
process.env.A // A
CLI
zx --env .env script.mjs
zx --env-file .env script.mjs
QnA

— Why not use dotenv directly?
— 1) Size does matter 2) We'd like to avoid internal vaults.

— Why not load .env by default?
— 1) Explicit is better than implicit 2) Runtime itself (like bun) may provide the feature.

Chore

v8.3.0: – Pipes of Steel

Compare Source

A few weeks ago zx took a part in OSS Library Night 🎉
Many thanks to the organizers and contributors who have boosted the project with their pull requests!

Today we are releasing the zx with a huge bunch of new features and improvements.

Features

API
  • Implemented [Symbol.asyncIterator] API for ProcessPromise #​984 #​998 #​1000
    Now you can iterate over the process output using for await loop from any point of the process execution.
const process = $`sleep 0.1; echo Chunk1; sleep 0.1; echo Chunk2; sleep 0.2; echo Chunk3; sleep 0.1; echo Chunk4;`
const chunks = []

await new Promise((resolve) => setTimeout(resolve, 250))
for await (const chunk of process) {
  chunks.push(chunk)
}

chunks.length //  4
chunks[0]     // 'Chunk1'
chunks[3]     // 'Chunk4'
  • zx version is available via JS API #​986
import { version } from 'zx'
const [major] = (version || '').split('.').map(Number)
if (major < 6)
  throw new Error('zx >= 6 is required')
Pipes
  • Enabled stream picking for pipe() #​1023
const p = $`echo foo >&2; echo bar`
const o1 = (await p.pipe.stderr`cat`).toString()
const o2 = (await p.pipe.stdout`cat`).toString()

assert.equal(o1, 'foo\n')  // <- piped from stderr
assert.equal(o2, 'bar\n')  // <- stdout
  • Added signal handling on piping #​992
const ac = new AbortController()
const { signal } = ac
const p = $({ signal, nothrow: true })`echo test`.pipe`sleep 999`
setTimeout(() => ac.abort(), 50)

try {
  await p
} catch ({ message }) {
  message // The operation was aborted
}
  • Added direct piping to file shortcut #​1001
// before
await $`echo "Hello, stdout!"`.pipe(fs.createWriteStream('/tmp/output.txt'))

// after
await $`echo "Hello, stdout!"`.pipe('/tmp/output.txt')
CLI
  • Provided $.defaults setting via ZX_-prefixed environment variables #​988 #​998
ZX_VERBOSE=true ZX_SHELL='/bin/bash' zx script.mjs
zx --env=/path/to/some.env script
  • Landed installation registry customization #​994
zx --install --registry=https://registry.yarnpkg.com script.mjs

Fixes

Docs

Chores

Merry Christmas! 🎄🎅🎁

v8.2.4: – Leaky Faucet

Compare Source

  • Fixed bun async_hooks compatibility #​959

v8.2.3: – Golden Wrench

Compare Source

This release continues the work on pipe API enhancements:

const { stdout } = await $({ halt: true })`echo "hello"`
 .pipe`awk '{print $1" world"}'`
 .pipe`tr '[a-z]' '[A-Z]'`
 .run()

stdout // 'HELLO WORLD'
  • Let $ be piped directly from streams #​953
const getUpperCaseTransform = () =>
  new Transform({
    transform(chunk, encoding, callback) {
      callback(null, String(chunk).toUpperCase())
    },
  })

// $ > stream (promisified) > $ 
const o1 = await $`echo "hello"`
  .pipe(getUpperCaseTransform())
  .pipe($`cat`)

o1.stdout //  'HELLO\n'

// stream > $
const file = tempfile()
await fs.writeFile(file, 'test')
const o2 = await fs
  .createReadStream(file)
  .pipe(getUpperCaseTransform())
  .pipe($`cat`)

o2.stdout //  'TEST'
const file = tempfile()
const fileStream = fs.createWriteStream(file)
const p = $`echo "hello"`
  .pipe(getUpperCaseTransform())
  .pipe(fileStream)
const o = await p

p instanceof WriteStream             // true
o instanceof WriteStream             // true
o.stdout                             // 'hello\n'
o.exitCode;                          // 0
(await fs.readFile(file)).toString() // 'HELLO\n'

We've also slightly tweaked up dist contents for better compatibility with bundlers #​957

v8.2.2

Compare Source

What's Changed

Full Changelog: google/zx@8.2.1...8.2.2

v8.2.1

Compare Source

  • #​936 fixes endless streams piping
  • #​930 enables custom extensions support

v8.2.0

Compare Source

Pipes supercharge today! 🚀

Features

  • Delayed piping. You can fill dependent streams at any time during the origin process lifecycle (even when finished) without losing data. #​914
const result = $`echo 1; sleep 1; echo 2; sleep 1; echo 3`
const piped1 = result.pipe`cat`
let piped2

setTimeout(() => {
  piped2 = result.pipe`cat`
}, 1500)

await piped1
assert.equal((await piped1).toString(), '1\n2\n3\n')
assert.equal((await piped2).toString(), '1\n2\n3\n')
const file = tempfile()
const fileStream = fs.createWriteStream(file)
const p = $`echo "hello"`
  .pipe(
    new Transform({
      transform(chunk, encoding, callback) {
        callback(null, String(chunk).toUpperCase())
      },
    })
  )
  .pipe(fileStream)

p instanceof WriteStream             // true
await p === fileStream               // true
(await fs.readFile(file)).toString() // 'HELLO\n'

Chore

v8.1.9

Compare Source

Today's release is a minor update that includes:

Enhancements

  • We have replaced ProcessOutput fields with lazy getters to reduce mem consumption #​903, #​908
  • Reduced ReDos risks for codeblock patterns #​906
  • Kept argv reference on update #​916
  • Strengthened Shell interface to properly handle sync mode #​915:
expectType<ProcessPromise>($`cmd`)
expectType<ProcessPromise>($({ sync: false })`cmd`)
expectType<ProcessOutput>($({ sync: true })`cmd`)
expectType<ProcessOutput>($.sync`cmd`)

Fixes

v8.1.8

Compare Source

  • Apply the proper TeplateStringArray detection #​904, #​905
  • PromiseProcess got lazy getters to optimize mem usage #​903

v8.1.7

Compare Source

Step by step on the road to improvements

Fixes

Finally, we've fixed the issue with piped process rejection #​640 #​899:

const p1 = $`exit 1`.pipe($`echo hello`)
try {
  await p1
} catch (e) {
  assert.equal(e.exitCode, 1)
}

const p2 = await $({ nothrow: true })`echo hello && exit 1`.pipe($`cat`)
assert.equal(p2.exitCode, 0)
assert.equal(p2.stdout.trim(), 'hello')

Enhancements

Added cmd display to ProcessPromise #​891:

const foo = 'bar'
const p = $`echo ${foo}`

p.cmd // 'echo bar'

and duration field to ProcessOutput #​892:

const p = $`sleep 1`.nothrow()
const o = await p

o.duration // ~1000 (in ms)

Enabled zurk-like pipe string literals #​900:

const p = await $`echo foo`.pipe`cat`
p.stdout.trim() // 'foo'

v8.1.6

Compare Source

Improvements & Fixes
  • The $.preferLocal option now also accepts a directory #​886, #​887.
$.preferLocal = true             // injects node_modules/.bin to the $PATH
$.preferLocal = '/foo/bar'       // attaches /foo/bar to the $PATH
$.preferLocal = ['/bar', '/baz'] // now the $PATH includes both /bar and /baz

Why not just $.env['PATH'] = 'extra:' + '$.env['PATH']?
Well, the API internally does the same, but also handles the win paths peculiarities.

  • Provided $.killSignal option for the symmetry with the $.timeoutSignal. You can override the default termination flow #​885:
$.killSignal = 'SIGKILL'

const p = $({nothrow: true})`sleep 10000`
setTimeout(p.kill, 100)
  
(await p).signal // SIGKILL
  • $ opt presets became chainable #​883:
const $$ = $({ nothrow: true })
assert.equal((await $$`exit 1`).exitCode, 1)

const $$$ = $$({ sync: true }) // Both {nothrow: true, sync: true} are applied
assert.equal($$$`exit 2`.exitCode, 2)
  • Enhanced the internal Duration parser #​884:
const p = $({timeout: '1mss'})`sleep 999` // raises an error now
  • Abortion signal listeners are now removed after the process completes #​881, #​889, zurk#12, zurk#13.
  • Extended integration tests matrix, added nodejs-nightly builds and TS dev snapshots #​888

v8.1.5

Compare Source

We've rolled out a new release!

Fixes

  • Added the minimist typings to the dts bundle. #​872 brings the fix.
  • Re-enabled the YAML extra
    API. #​870 #​879

Chores

  • Clarified cd(), within() and syncProcessCwd() interactions. #​878
  • Included mention of the cwd option in the documentation. #​868
  • Test enhancements. #​877 #​880

v8.1.4

Compare Source

We continue optimizing bundles and CI/CD pipelines.

  • Update @​webpod/ps to v0.0.0-beta.7 to sync internal zurk version. #​855
  • Split vendor chunk to reduce the zx/core entry size. #​856
  • Add bundle size check. #​857
  • Refactor the testing flow, remove duplicated tasks. #​861
  • Add missing types for the global defaults. #​864
  • Omit redundant YAML API extras. #​866

Which gives us: 897 kB → 829 kB (-7.58%)

v8.1.3

Compare Source

Nothing special today. We just keep improving the implementation.

Features

import {$} from 'zx'
  • zx/cli exports its inners to allow more advanced usage.
    Imagine, your own CLI tool that uses zx as a base:
    #​828
#!/usr/bin/env node

import './index.mjs'
import {main} from 'zx/cli'

main()
  • Provide intermediate store configuration for fine-grained control of memory usage.
    #​650, #​849
const getFixedSizeArray = (size) => {
  const arr = []
  return new Proxy(arr, {
    get: (target, prop) =>
      prop === 'push' && arr.length >= size
        ? () => {}
        : target[prop],
  })
}
const store = {
  stdout: getFixedSizeArray(1),
  stderr: getFixedSizeArray(1),
  stdall: getFixedSizeArray(0),
}

const p = await $({ store })`echo foo`

p.stdout.trim() //  'foo'
p.toString()    // ''
  • Introduced sync methods for ps:
    #​840
import { ps } from 'zx'

const list1 = await ps()
const list2 = await tree()

// new methods
const list3 = ps.sync()
const list4 = tree.sync()

Chore

v8.1.2

Compare Source

Every new zx version is better than previous one. What have we here?

Features

  • Added ProcessPromise.verbose() to enhance debugging experience.
    #​820, #​710
const p = $`echo foo`
p.quiet()        // enable silent mode
p.quiet(false)   // then disable
p.verbose()      // enable verbose/debug mode
p.verbose(false) // and turn it off

await p
  • Aligned ProcessPromise.isSmth() API:
    #​823
const p = $`echo foo`

p.isHalted()
p.isVerbose()
p.isQuiet()
p.isNothrow()

Bug Fixes

  • fix: apply EOL ensurer to the last chunk only #​825
  • fix(cli): return exit code 1 on incorrect inputs #​826
  • fix: set cjs bundle as legacy main entrypoint #​827

Chore

v8.1.1

Compare Source

This release brings a pinch of sugar and minor fixes.

Features
  • Introduced $.preferLocal option to prefer node_modules/.bin located binaries over globally system installed ones.
    #​798
$.preferLocal = true

await $`c8 npm test`

await $({ preferLocal: true })`eslint .`
const p = $`echo 'foo\nbar'`

await p.text()        // foo\n\bar\n
await p.text('hex')   //  666f6f0a0861720a
await p.buffer()      //  Buffer.from('foo\n\bar\n')
await p.lines()       // ['foo', 'bar']
await $`echo '{"foo": "bar"}'`.json() // {foo: 'bar'}
  • ProcessPromise now exposes its signal reference.
    #​816
const p = $`sleep 999`
const {signal} = p

const res = fetch('https://example.com', {signal})

setTimeout(() => p.abort('reason'), 1000)
Fixes
  • CLI flag --quiet is mapped to $.quiet option. #​813
  • Module conditional exports are properly sorted now. #​812
  • A newline character is appended to the output of ProcessPromise if it's missing. #​810

v8.1.0

Compare Source

This new release is a big deal. It brings significant improvements in reliability and compatibility.

New features

Added usePwsh() helper to switch to PowerShell v7+ #​790

import {usePwsh, useBash} from 'zx'

usePwsh()
$.shell // 'pwsh'

useBash()
$.shell // 'bash'

timeout is now configurable $ opts #​796

import {$} from 'zx'

await $({ timeout: 100 })`sleep 999`

$.timeout = 1000            // Sets default timeout for all commands
$.timeoutSignal = 'SIGKILL' // Sets signal to send on timeout

await $`sleep 999`

Added --cwd option for CLI #​804

zx --cwd=/some/path script.js

Introduced tmpdir and tmpfile helpers #​803

import {tmpdir, tmpfile} from 'zx'

t1 = tmpdir()          // /os/based/tmp/zx-1ra1iofojgg/
t2 = tmpdir('foo')     // /os/based/tmp/zx-1ra1iofojgg/foo/

f1 = tmpfile()         // /os/based/tmp/zx-1ra1iofojgg
f2 = tmpfile('f.txt')  // /os/based/tmp/zx-1ra1iofojgg/foo.txt
f3 = tmpfile('f.txt', 'string or buffer')
  • Support CRLF for markdown script #​788
  • Added help digest for man #​806
  • Added compatibility with Deno 1.x. → zx seems to be working with Deno 1.x.

v8.0.2

Compare Source

In this release:

  • Added configurable detached option (#​782)
  • Fixed pkg typings entries for tsd tests (#​780)

v8.0.1

Compare Source

In this release:

  • Added feature: add stdio option (#​772)
  • Added feature: support signal opt (#​769)
  • Fixed: additional process.kill fallback for bun (#​770)

v8.0.0

Compare Source

We are thrilled to announce the release of zx v8.0.0! 🎉

With this release, we have introduced a lot of new features, improvements, and bug fixes.
We have also made some breaking changes, so please read the following release notes carefully.

🚀 New Shiny Features

Squashed deps: we use esbuild with custom plugins to forge js bundles and dts-bundle-generator for typings 2acb0f, #​722

More safety, more stability and significantly reduced installation time. Zx now is ~20x smaller.

npx zx@8.0.0
npm install zx@8.0.0

Options presets are here. To implement this, we have also completely refactored the zx core, and now it's available as a separate package – zurk\ aeec7a, #​733, #​600

const $$ = $({quiet: true})
await $$`echo foo`

$({nothrow: true})`exit 1`

We have introduced $.sync() API\ 1f8c8b, #​738, #​681, 1d8aa9, #​739

import {$} from 'zx'

const { output } = $.sync`echo foo` // foo

You can also override the internal API to implement pools, test mocking, etc.

$.spawnSync = () => {} // defaults to `child_process.spawnSync`

The input option is now available to pass data to the command.\ b38972, #​736

const p1 = $({ input: 'foo' })`cat`
const p2 = $({ input: Readable.from('bar') })`cat`
const p3 = $({ input: Buffer.from('baz') })`cat`
const p4 = $({ input: p3 })`cat`
const p5 = $({ input: await p3 })`cat`

AbortController has been introduced to abort the command execution. It's available via the ac option.\ fa4a7b, #​734, #​527

const ac = new AbortController()
const p = $({ ac })`sleep 9999`

setTimeout(() => ac.abort(), 100)

If not specified, the default instance will be used. Abortion trigger is also available via PromiseResponse:

const p = $`sleep 9999`
setTimeout(() => p.abort(), 100)

kill method is exposed now. To terminate any (not only zx starter) process:

import { kill } from 'zx'

await kill(123)
await kill(123, 'SIGKILL')

Btw, we have replaced ps-tree with @​webpod/ps & @​webpod/ingrid, and exposed ps util:

import {ps} from 'zx'

const children = await ps.tree(123)
/**
 [
 {pid: 124, ppid: 123},
 {pid: 125, ppid: 123}
 ]
 */
const children2 = await ps.tree({pid: 123, recursive: true})
/**
 [
 {pid: 124, ppid: 123},
 {pid: 125, ppid: 123},

 {pid: 126, ppid: 124},
 {pid: 127, ppid: 124},
 {pid: 128, ppid: 124},

 {pid: 129, ppid: 125},
 {pid: 130, ppid: 125},
 ]
 */

Introduced $.postfix option. It's like a $.prefix, but for the end of the command. fb9554, #​756, #​536

import {$} from 'zx'

$.postfix = '; exit $LastExitCode' // for PowerShell compatibility

minimist API exposed\ #​661

import { minimist } from 'zx'

const argv = minimist(process.argv.slice(2), {})

Fixed npm package name pattern on --install mode 956dcc, #​659, #​660, #​663

import '@&#8203;qux/pkg'       // valid
import '@&#8203;qux/pkg/entry' // was invalid before and valid now
⚠️ Breaking changes

We've tried our best to avoid them, but it was necessary.

  1. $.verbose is set to false by default, but errors are still printed to stderr. Set $.quiet = true to suppress all output.\ cafb90, #​745, #​569

    $.verbose = true // everything works like in v7
    
    $.quiet = true // to completely turn off logging
  2. ssh API was dropped. Install webpod package instead.\ 8925a1, #​750

    // import {ssh} from 'zx' ↓
    import {ssh} from 'webpod'
    
    const remote = ssh('user@host')
    await remote`echo foo`
  3. zx is not looking for powershell anymore, on Windows by default. If you still need it, use the usePowerShell helper:\ 24dcf3, #​757

    import { usePowerShell, useBash } from 'zx'
    
    usePowerShell() // to enable powershell
    useBash()       // switch to bash, the default
  4. Process cwd synchronization between $ invocations is disabled by default. This functionality is provided via an async hook and can now be controlled directly.\ d79a63, #​765

    import { syncProcessCwd } from 'zx'
    
    syncProcessCwd() // restores legacy v7 behavior
🧰 Other Improvements

Configuration

📅 Schedule: Branch creation - "* * * * 0" (UTC), Automerge - At any time (no schedule defined).

🚦 Automerge: Enabled.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR has been generated by Renovate Bot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

0 participants