Skip to content

henrycunh/haxx

Repository files navigation

haxx

easily create and run scripts using javascript


getting startedcommandsapi

Features

  • 🔀 Process DX - easily manage and run processes
  • 📦 Javascript ESM - makes writing scripts easier, through javascript
  • 🔌 Great IO - provides easy to use IO functions, for known formats
  • 🧑‍💻 Opinionated - it's a great tool for writing tools, with tools inside

Getting started

It's as simple as creating a script file with a .mjs extension

#!/usr/bin/env haxx

const lastTag = await $`git tag | tail -n 1`
const tagMessage = String(await $`git tag -l -n9 ${lastTag}`)
    .match(/\s{2,}(.+)/)[1]
console.log(`Last tag message: ${tagMessage}`)

And running it

haxx my-script.mjs

Installation

You can either install it globally

npm i -g haxx
haxx my-script.mjs

Or run it through npx or any other package manager execute

npx -y haxx my-script.mjs

API

$

Executes a given command and returns a promise of the output.

Everything passed through ${...} will be automatically escaped and quoted.

const dirToRemove = 'my nice dir'
await $`rm -rf ${dirToRemove}` // rm -rf 'my nice dir'

You can pass arrays as arguments

const dirs = ['dir1', 'dir2']
await $`ls ${dirs}` // ls dir1 dir2

You can catch process exit codes upon a failing

try {
    await $`exit 1`
} catch (process) {
    console.log(`Exit code: ${process.exitCode}`)
    console.log(`Error: ${process.stderr}`)
}

You can pipe directly from the promise to any other stream

$`watch -n1 ls`.pipe(process.stdout)

read

Lets you read files easily, and specify formats

const content = await read`my-file.txt`

const package = await read.json`package.json`
console.log(package.version)

const deployment = await read.yaml`deployment.yaml`
console.log(deployment.metadata.name)

write

Lets you write files easily, and specify formats

await write('my-file', 'Hello world') 
// Hello World

await write.json('object.json', { hello: 'world' })
// { "hello": "world" }

await write.yaml('object.yaml', { hello: 'world' })
// hello: world

io

Gives you a nice interface for reading and saving files

const { data: pkg, save } = await io.json`package.json`
pkg.version = '1.0.1'
await save()

const { data: deployment, save: saveDeployment } = await io.yaml`deployment.yaml`
deployment.spec.template.spec.containers[0].image = 'my-new-image'
await saveDeployment()

exists

Checks if a file or directory exists

if (!exists('key')) {
    await write('key', Math.random().toString().slice(2))
}

remove

Removes a file or directory

remove('my-file')

cd

Changes the directory

await $`ls`
cd('another-directory')
await $`ls`

template

Lets you replace variables in a template

const phrase = template({ name: 'world'}, 'Hello {{ name }}')

const filled = template.file({ GITHUB_TOKEN: '...' }, 'my-template')

Included batteries

  • kleur - a nice color library
  • kleur-template - easier coloring through templating
  • glob - utility for globbing files
  • yaml - a yaml parser
  • os - the os package
  • path - the path package
  • minimist - your arguments parsed, availabe through the global constant argv

Acknowledgements

This project is heavily inspired by zx and fsxx, down to the code.

Check them out!