Writing Shell Scripts in JavaScript with ZX
Tags: code, typescript, bash, automation
Published: 2022-06-24 07:39:17

---
title: Writing Shell Scripts in JavaScript with ZX
published: true
date: 2022-06-23 00:00:00 UTC
tags: Code,TypeScript,Bash,Automation
canonical_url: https://codeandchaos.com/blog/2022/2022-06-23-WritingScripts
---

**Photo by JÉSHOOTS** from [Pexels](https://www.pexels.com/photo/blurred-motion-of-illuminated-railroad-station-in-city-253647/)

I was working in the past on a project, that was still requiring us to do manual releases. We followed a short guide consisting of Terminal commands. Only a minor adjustment was needed for each new release. We could have greatly benefited from writing a simple bash script. However I am not a sysadmin and tend to rarely write shell scripts. It would take way too much time to debug and create a working bash script. We decided copy and pasting code is just more efficient.

Luckily the developers at Google also did not want to write bash scripts. However apperantly they got the resoruces to create something even better:

[zx - A tool for writing better scripts](https://github.com/google/zx)

It allows you to combine JavaScript with the Bash commands to create complex scripts. At its core its just a simpler wrapper syntax for working with NodeJS `child_process`.

## The Release Script

Our build steps are basically:

1. Bump the version in package.json with the command `npm version patch`
2. Pass the new version number to the _releaseCMD_

The reason to do this manually was that there is no easy way to read the new version number from the `package.json` to store it in a variable to pass it into the _releaseCMD_

## The ZX Script

### Output Text to the console

Its always useful to output stuff to the console. You can simply use `console.log("Hello")` to output text on the console.

### Execute Commands

As alternative if you want to execute any terminal command like `echo` to output text. You write it as
` $\``echo Hello `

### Read JSON

The [Github Page of ZX](https://github.com/google/zx) has a list of typical commands and examples what you can do with them. One of them is to read the package version

```
const { version } = await   fs.readJson("./package.json");
```

### Let's put it all together

I created a directory `scripts` that will contain all the future projects scripts and created the file `release.mjs`

**/scripts/release.mjs**

```javascript
console.log('Running Release Script')
await $`npm version patch` // Bumps package version
const { version } = await fs.readJson('./package.json') // Reads new package version
try {
  await $`echo releaseCMD -version ${version}` //Replace with actual command
} catch (p) {
  console.log(`Error: ${p.stderr} ExitCode ${p.exitCode}`) //Logs Error to the terminal
}
```

## Executing the Script

You either can install zx globally with the command

```
npm i -g zx
```

or you can run it with `npx zx <scriptname>`.

Personally as soon as I am done with the script I don't want to deal with this anymore. I want that every team member can use the script without any explanation.
Thus I added it as a script in `package.json`

**/package.json**

```json
{
  "scripts": {
    "release": "npx zx ./scripts/release.tjs"
  }
}
```

Now you can run it like any other script `npm run release`

# Conclusion

Unfortunatly I did not have a lot of time to play around with ZX. I am sure that it is capable of creating very complex scripts.

For my usecase I did not look into executing scripts as an admin, or creating cross platform scripts etc. Again I am not a sysadmin.

In the end, I think ZX is a great way of creating shell scripts without having to deal with BASH. Thus with your TypeScript/JavaScript knowledge you can quickly create scripts to automate the boring stuff.