/jb

jb: write script in an easier way than bash

Primary LanguageZigMIT LicenseMIT

jb = javascript + bash

#!/usr/bin/env jb

$`ls -l`

var output = $1`whoami`
$(`echo ${output}`)

Bash is great, but when it comes to writing more complex scripts, many people prefer a more convenient programming language. JavaScript is a perfect choice. The jb provides useful wrappers. The jb is a bun port of zx, the advantage is that you don't need to install node, and jb is just a standalone binary.

Install

jb is just a standalone binary, so you can download and put it in your PATH. Or install it via nami

nami install jb

Documentation

Just write your scripts in a file with an .js

Add the following shebang to the beginning of your jb scripts:

#!/usr/bin/env jb

Now you will be able to run your script like so:

chmod +x ./script.js
./script.js

Or via the jb executable:

jb ./script.js

Or executes remote script

jb https://www.txthinking.com/script.js

All functions ($, cd, fetch, etc) are available straight away without any imports.

$`command`

Executes a given command, keep the default behavior of stdout and stderr like bash

$`ls -l`

Or put a variable in command

var name = 'hello'
$(`mkdir ${name}`)

You can pass an array of arguments if needed:

var flags = [
  '-l',
  '-h',
]
$(`ls ${flags.join(' ')}`)

If the executed program failed, error will be thrown.

$`brook unknownsubcommand`

$1`command`

Same as $`command` , but will return stdout and trim space, as you know, 1 is STDOUT

var count = $1`ls -l | wc -l`
$(`echo ${count}`)

env()

Set env

env('HELLO', "JB")
$`echo $HELLO` // => JB

cd()

Changes the current working directory.

cd('/tmp')
$`pwd` // => /tmp

question()

var name = question('What is your name? ')

confirm()

var ok = confirm('Do you really want to leave?');

sleep()

sleep(1000)

now()

Current unix timestamp

var t = now()

echo()

A console.log() alternative

echo('hello')

which()

File path or null

var bin = which('brook')

exit()

Exit the script

exit()

exists_file()

file exists or not

var yn = exists_file('path/to/file.txt')

read_file()

Read the text from local file

var str = read_file('path/to/file.txt')

write_file()

Write text to local file

write_file('path/to/file.txt', 'some text')

append_file()

Append text to local file

append_file('path/to/file.txt', 'some text')

cp()

Copy file or http file from zip/tar.gz/tar.xz to local

cp('https://github.com/txthinking/brook/releases/latest/download/brook_darwin_arm64', '/tmp/brook');

Copy file from zip

7z l ~/Downloads/bun-darwin-aarch64.zip
   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2023-06-03 15:54:41 D....            0            0  bun-darwin-aarch64
2023-06-03 15:54:41 .....     46584592     16787941  bun-darwin-aarch64/bun
------------------- ----- ------------ ------------  ------------------------
2023-06-03 15:54:41           46584592     16787941  1 files, 1 folders
cp('$HOME/Downloads/bun-darwin-aarch64.zip', 'bun-darwin-aarch64/bun', '/tmp/bun');

Copy multiple files from tar.gz

tar ztf ~/Downloads/cowsay_2.0.4_macOS_arm64.tar.gz
LICENSE
doc/cowsay.1
cowsay
cowthink
cp('$HOME/Downloads/cowsay_2.0.4_macOS_arm64.tar.gz', {
    'cowsay': '/tmp/cowsay',
    'cowthink': '/tmp/cowthink',
});

Copy multiple files from tar.xz

tar Jtf ~/Downloads/shadowsocks-v1.15.3.aarch64-apple-darwin.tar.xz
sslocal
ssserver
ssurl
ssmanager
ssservice
cp('https://github.com/shadowsocks/shadowsocks-rust/releases/latest/download/shadowsocks-v1.15.3.aarch64-apple-darwin.tar.xz', {
    'sslocal': '/tmp/sslocal',
    'ssserver': '/tmp/ssserver',
});

Async Functions

stdin()

Returns the stdin as a string.

var s = await stdin()
echo(`got ${s} from pipe`);
echo hello | jb ./script.js

retry()

Will return after the first successful attempt, or will throw after specifies attempts count.

var s = await retry(() => $1`curl https://www.txthinking.com`)

// delay 1s
var s = await retry(() => $1`curl https://www.txthinking.com`, 1000)

// delay 1s and max 3 times
var s = await retry(() => $1`curl https://www.txthinking.com`, 1000, 3)

Web, Node, Bun

built-in Web API such as fetch

var res = await fetch('https://www.txthinking.com');

built-in node

import os from 'node:os';

echo(os.homedir());

built-in bun

Bun.serve({
    port: 8080,
    hostname: '127.0.0.1',
    fetch(req) {
        return new Response("jb!");
    },
});

Executing commands on remote hosts

The jb uses sshexec to execute commands on remote hosts.

$`sshexec -s 1.2.3.4:22 -u user -p pass -c 'ls -l'`

Download file from remote

$`sshexec -s 1.2.3.4:22 -u user -p pass --download /server/path/to/file --to /local/path/to/file`

Upload file to remote

$`sshexec -s 1.2.3.4:22 -u user -k path/to/private/key --upload /local/path/to/file --to /server/path/to/file`

License

jb itself is MIT-licensed. Refer to the dependencies license for information.