Deno shell tools inspired by zx
#!/usr/bin/env dzx
/// <reference path="https://deno.land/x/[email protected]/types.d.ts" />
$.verbose = true;
$.shell = "/usr/local/bin/zsh";
console.log(`Hello from ${$.blue.bold("dzx")}!`);
const branch = await $`git branch --show-current`;
await $`dep deploy --branch=${branch}`;
await Promise.all([
$`deno lint`,
$`deno fmt --check`,
$`deno test --allow-all`,
]);
const name = "foo bar";
await $`mkdir ./tmp/${name}`; // Params will be quoted if required: /tmp/'foo bar'.
cd("tmp/foo bar");
console.log(Deno.cwd()); // ./tmp/foo bar
cd("tmp");
console.log(Deno.cwd()); // ./tmp
await async.delay(1000);
const basename = path.basename(import.meta.url);
const stdin = await io.readAll(Deno.stdin);
await fs.ensureDir("./tmp");
deno install --allow-all --unstable -f https://deno.land/x/[email protected]/dzx.ts
--unstable
is required for thebundle
command which usesDeno.emit
, forstd/fs/copy
and for web workers.
To start writing a dzx script, add next shebang at the beginning of your script:
#!/usr/bin/env dzx
To enable typings for typescript in your IDE, you can add a tripple slash reference to the top of the file,
#!/usr/bin/env dzx
/// <reference path="https://deno.land/x/[email protected]/types.d.ts" />
or you can import all symbol directly from the dzx/mod.ts
module instead of
using globals.
#!/usr/bin/env dzx
import { $, cd, fs, io, log, path } from "https://deno.land/x/[email protected]/mod.ts";
After making your script executable,
chmod +x ./script.ts
you can simply run it with:
./script.ts
You can use dzx
without installation by using next shebang. This also allows
you to explicitly set the permissions for your script.
#!/usr/bin/env deno run --allow-run --allow-read --allow-env https://deno.land/x/[email protected]/dzx.ts
/// <reference path="https://deno.land/x/[email protected]/types.d.ts" />
console.log(`Hello ${$.blue.bold("world")}!`);
This is currently an exerminental feature. Permission flags doens't support values currently. Read permissions are required by default.
If dzx
is called with -w
or --worker
, the script is executed inside an
isolated web worker. If enabled, you can pass explicit permissions directly to
the dzx
cli.
#!/usr/bin/env dzx --worker --allow-read
/// <reference path="https://deno.land/x/[email protected]/types.d.ts" />
console.log(`Hello from ${$.blue.bold("worker")}!`);
With dzx
you can run the js
/ts
code blocks from a Markdown file as if they
were a regular script. This is very convenient when you want to blend some
nicely formatted documentation in with the actual steps of execution.
Give it a try by running:
dzx ./examples/markdown.md
See the markdown example for further documentation and notes.
-
$`command`
: Executes a shell command.const count = parseInt(await $`ls -1 | wc -l`); console.log(`Files count: ${count}`);
If the executed program was successful, an instance of
ProcessOutput
will be return.class ProcessOutput { readonly stdout: string; readonly stderr: string; readonly combined: string; readonly status: Deno.ChildStatus; toString(): string; }
If the executed program returns a non-zero exit code, a
ProcessError
will be thrown.The
ProcessError
class extends from theError
class and implements all properties and methods fromProcessOutput
.try { await $`exit 1`; } catch (error) { console.log(`Exit code: ${error.status.code}`); console.log(`Error: ${error.stderr}`); }
-
$s`command`
: Executes a shell command and only returns its exit code (without throwing an error)const trueStatus = await $s`true`); console.log(trueStatus); // -> 0
If the executed program returns a non-zero exit code, no error will be thrown. Either the non-zero code will be the return value, or a
1
will be returned by default.const falseStatus = await $s`false`); console.log(falseStatus); // -> 1
-
$o`command`
: Executes a shell command and only returns its trimmed stdout (without throwing an error)const stdout = await $o`pwd`); console.log(stdout); // -> '/home/code/project
If the executed program returns a non-zero exit code, no error will be thrown. Either the failed processes stdout will be the return value, or an empty string will be returned by default
const stdout = await $o`echo 'hello' >&2; exit 1;`); console.log(stdout); // -> ""
-
$e`command`
: Executes a shell command and only returns its trimmed stderr (without throwing an error)const stderr = await $e`pwd`); console.log(stderr); // -> ""
If the executed program returns a non-zero exit code, no error will be thrown. Either the failed processes stderr will be the return value, or an empty string will be returned by default
const stderr = await $e`echo 'hello' >&2; exit 1;`); console.log(stderr); // -> "hello"
-
cd()
: Change the current working directory. If path does not exist, an error is thrown. The path is always relative to the originalcwd
, unless the path is an absolute path or starts with~
which indecates the home directory.console.log(Deno.cwd()); // --> /example/directory cd("foo/bar"); console.log(Deno.cwd()); // --> /example/directory/foo/bar cd("foo/baz"); console.log(Deno.cwd()); // --> /example/directory/foo/baz cd("/tmp"); console.log(Deno.cwd()); // --> /tmp cd("~/Documents"); console.log(Deno.cwd()); // --> [HOME]/Documents
-
quote`string`
: The quote methods quotes safly a string. by default theshq
package is used. Can be overidden with$.quote
.
-
$.[style]: Cliffy's color module. A chainable wrapper for Deno's
std/fmt/colors
module. Available on the global$
symbol.console.log($.blue.bold("Hello world!"));
-
async: Deno's
std/async
module.await async.delay(1000);
-
path: Deno's
std/path
module.const basename = path.basename(import.meta.url); const options: path.GlobToRegExpOptions = { os: "linux" }; const regex: RegExp = path.globToRegExp("*.ts", options);
-
io: Deno's
std/io
module.const fileReader = await Deno.open("./example.txt"); for await (let line of io.readLines(fileReader)) { console.log(line); }
-
streams: Deno's
std/streams
module.const data = await streams.readAll(Deno.stdin);
-
fs: Deno's
std/fs
module.fs.ensureDir("./tmp");
-
log: Deno's
std/log
module.log.info("Some info!");
-
flags: Deno's
std/flags
module.const args: flags.Args = flags.parse($.args);
- $.shell: Set the shell that is used by
$`command`
. Default:/bin/bash
- $.prefix: Command prefix. Default:
set -euo pipefail;
. - $.mainModule: The executed dzx script.
- $.verbose: Enable debugging output (log shell commands and execution time).
- $.throwErrors: Throw errors instead of calling
Deno.exit
. - $.args: Equivalent to
Deno.args
, but without the script name as first argument. - $.startTime: The execution start time in ms.
- $.time: The time left since execution start (now() - $.startTime).
- $.quote: Parser method that is used to safely quote strings. Used by:
$`command`
Usage: dzx [script] [args...]
Version: 0.3.1
Description:
π¦ A custom deno runtime for fun.
Options:
-h, --help - Show this help.
-V, --version - Show the version number for this program.
-A, --allow-all - Allow all permissions. (Depends: --worker)
--allow-env - Allow environment access. (Depends: --worker)
--allow-hrtime - Allow high resolution time measurement. (Depends: --worker)
--allow-net - Allow network access. (Depends: --worker)
--allow-ffi - Allow loading dynamic libraries. (Depends: --worker)
--allow-read - Allow file system read access. (Depends: --worker)
--allow-run - Allow running subprocesses. (Depends: --worker)
--allow-write - Allow file system write access. (Depends: --worker)
-w, --worker - Run script in an isolated web worker with it's own permissions.
Commands:
bundle [script] - Bundle an dzx script to a standalone deno sript.
compile [compile-options...] [script] [script-options...] - Combile an dzx script to a standalone binary.
eval <code> - Evaluate a dzx script from the command line.
repl - Start a dzx repl.
upgrade - Upgrade dzx executable to latest or given version.
-
dzx
[script] [...args]
: Run a local or remote dzx script (optional in a web worker).dzx --worker ./example.ts
-
dzx bundle
[script]
: Bundle a dzx script to a standalone deno script. Can also read from stdin.dzx bundle ./example.ts > bundle.js deno run --allow-read --allow-env --allow-run bundle.js
-
dzx compile
[...permissions] [script] [...script-arguments]
: Compile an dzx script to a standalone binary. Can also read from stdin.dzx compile --allow-read --allow-env --allow-run ./example.ts --port 8080
Note that when reading from
stdin
, you must separate "deno compile" flags (i.e. your permissions) from your "script args" with a double dash (--
), i.e.cat ./example.ts | dzx compile --allow-read -- --port 8080
It is also recommended when reading from
stdin
that you pass the --output flag with your permissions to specify the output file name, otherwise the compiled file will be emitted with a random value as its name. -
dzx eval: Evaluate a dzx script from command line.
dzx eval "console.log($.shell)"
Eval can also read from stdin:
echo "console.log($.shell)" | dzx eval
-
dzx repl: Start a dzx repl (Read eval print loop).
The
repl
command starts a deno repl bootstrapped with the dzx runtime code. -
dzx upgrade: Upgrade the
dzx
executable to latest or given version.Upgrade to latest version:
dzx upgrade
Upgrade to specific version:
dzx upgrade --version 3.0.0
List all available versions:
dzx upgrade --list-versions
Any kind of contribution is welcome!