Skip to content

Commit

Permalink
feat(export): add script exporting functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
umbopepato committed May 22, 2020
1 parent 80ad8d2 commit 399d5e3
Show file tree
Hide file tree
Showing 18 changed files with 467 additions and 218 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/test.yml
Expand Up @@ -11,12 +11,12 @@ jobs:
test:
strategy:
matrix:
deno: ['v1.0.0']
deno: ['v1.0.1']
os: [ubuntu-latest, macOS-latest, windows-latest]
runs-on: ${{ matrix.os }}

steps:

- uses: actions/checkout@v2

- name: Setup Deno
Expand Down
148 changes: 115 additions & 33 deletions README.md
@@ -1,9 +1,41 @@
# Velociraptor
<p align="center">
<img src="assets/logo.svg" width="350">
</p>

Velociraptor is a script runner for Deno, inspired by npm's package.json scripts. It offers a similar experience but with out-of-the-box support for declarative deno cli options, environment variables, concurrency and (soon) git hooks.
<p align="center">
Velociraptor is a script runner for Deno, inspired by npm's package.json scripts. It offers a similar experience but with out-of-the-box support for declarative deno cli options, environment variables, concurrency and (soon) git hooks.
</p>

<p align="center">

<img src="https://github.com/umbopepato/velociraptor/workflows/Deno%20CI/badge.svg"/>
<a href="https://doc.deno.land/https/deno.land/x/velociraptor@v1.0.0-beta.5/src/scripts_config.ts#ScriptsConfiguration"><img src="https://doc.deno.land/badge.svg"></a>
<img src="https://img.shields.io/badge/deno-%5E1.0.0-blue"/>
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-brightgreen"/></a>

</p>

<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->


- [Motivation](#motivation)
- [Install](#install)
- [Project status](#project-status)
- [Script files](#script-files)
- [Listing scripts](#listing-scripts)
- [Running scripts](#running-scripts)
- [Exporting scripts](#exporting-scripts)
- [Shell scripting](#shell-scripting)
- [Current working directory](#current-working-directory)
- [Shell completions](#shell-completions)
- [Known limitations](#known-limitations)
- [Upcoming features](#upcoming-features)
- [Contributing](#contributing)
- [License](#license)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

![Deno CI](https://github.com/umbopepato/velociraptor/workflows/Deno%20CI/badge.svg)
[![deno doc](https://doc.deno.land/badge.svg)](https://doc.deno.land/https/deno.land/x/velociraptor@v1.0.0-beta.5/src/scripts_config.ts#ScriptsConfiguration)

## Motivation

Expand All @@ -12,7 +44,7 @@ Mainly because Deno cli commands can easily become very long and difficult to re
## Install

```sh
$ deno install --allow-read --allow-env --allow-run -n vr https://deno.land/x/velociraptor/cli.ts
$ deno install --allow-read --allow-write --allow-env --allow-run -n vr https://deno.land/x/velociraptor/cli.ts
```

<details>
Expand All @@ -35,36 +67,20 @@ $ deno install ... https://deno.land/x/velociraptor@<version>/cli.ts
For example

```sh
$ deno install --allow-read --allow-env --allow-run -n vr https://deno.land/x/velociraptor@v1.0.0-beta.5/cli.ts
$ deno install --allow-read --allow-write --allow-env --allow-run -n vr https://deno.land/x/velociraptor@v1.0.0-beta.5/cli.ts
```

</details>

## Usage

```sh
$ vr [SCRIPT] [ADDITIONAL ARGS]...
# or
$ vr run <SCRIPT> [ADDITIONAL ARGS]...
```

**`SCRIPT`**
The identifier of the script to run.

**`ADDITIONAL ARGS`**
Any other argument, passed to the script. Unlike `npm run`, the `--` separator is not needed.

Run `vr` without arguments to see a list of available scripts.

Run `vr --help` for more guidance.
To get help with the CLI run `vr help`, or `vr help <SUBCOMMAND>` for specific commands.

## Project status

👨‍💻 WIP: until the Deno std library is stable there may be breaking changes here, use carefully and feel free to open an issue if you found a bug.
👨‍💻 WIP: until the Deno std library is stable there may be breaking changes here, use carefully and feel free to open an issue if you find a bug.

## Script files

To define scripts, create a file called `scripts.yaml` or `velociraptor.yaml` in your project folder.
To get started, create a file called `scripts.yaml` or `velociraptor.yaml` in your project folder:

```yaml
# scripts.yaml
Expand Down Expand Up @@ -237,7 +253,7 @@ scripts:
logfile: v8.log
```

### Multiple commands
### Compound commands and concurrency

If the script value is an array of commands, the commands are executed serially.

Expand All @@ -252,7 +268,7 @@ scripts:
tsconfig: tsconfig.json
```

To execute commands in parallel, list them in the `pll` property of an object.
To declare concurrent commands, list them in the `pll` property of an object.

```yaml
scripts:
Expand Down Expand Up @@ -284,9 +300,78 @@ scripts:

See [ScriptConfiguration](https://doc.deno.land/https/deno.land/x/velociraptor@v1.0.0-beta.5/src/scripts_config.ts#ScriptsConfiguration) for a detailed description of the structure of script files.

## Listing scripts

Run

```sh
$ vr
```

to see a list of available scripts.

## Running scripts

To run a script, use the `run` subcommand

```sh
$ vr run <SCRIPT> [ADDITIONAL ARGS]...
```

or, more concisely

```sh
$ vr [SCRIPT] [ADDITIONAL ARGS]...
```

|Arg or option|Description|
|:---|:---|
|`SCRIPT`|The identifier of the script to run.|
|`ADDITIONAL ARGS`|Any other argument, passed to the script. Unlike `npm run`, the `--` separator is not needed.|

For example, run

```sh
$ vr start
# or
$ vr run start
```

to execute the `start` script.

> If you enabled [shell completions](#shell-completions), trigger the autocomplete on one of this commands to get the available scripts as suggestions.
## Exporting scripts

You may find yourself in a situation where you want to use velociraptor to manage your scripts during development, but you're not comfortable installing it (or just can't install it) in your production environment.
In this case the `export` subcommand may be of help: it allows you to export one or more scripts as standalone executable shell files:

```sh
$ vr export [SCRIPTS]...
```

|Arg or option|Description|
|:---|:---|
|`SCRIPTS`|A space-separated list of scripts to export. If omitted, all the declared scripts are exported.|
|`-o, --out-dir`|The directory where the scripts will be exported (default: `bin`).|

For example, run

```sh
$ vr export start
```

to export the `start` script, together with its env variables, deno cli options etc. Now you can execute it by running

```sh
$ ./bin/start [ARGS]...
```

> Scripts exporting currently only supports `sh`.
## Shell scripting

Like in `npm` scripts, vr commands are executed inside a shell. The shell is determined by the `SHELL` env variable on Unix-like systems and by `ComSpec` on Windows, with respectively `sh` and `cmd.exe` as fallback values. To customize the shell without changing you default shell env variables you can use the `VR_SHELL` variable (a full path is requried).
Like in `npm` scripts, vr commands are executed inside a shell. The shell is determined by the `SHELL` env variable on Unix-like systems and by `ComSpec` on Windows, with respectively `sh` and `cmd.exe` as fallback values. To customize the shell without changing your default shell env variables you can use the `VR_SHELL` variable (a full path is requried).

The shell requirements are pretty much the same as [node's](https://nodejs.org/api/child_process.html#child_process_shell_requirements).

Expand All @@ -296,15 +381,13 @@ Velociraptor searches for script files up the folder tree starting from the dire

## Shell completions

To enable shell tab-completion for Velociraptor commands, add the following line to your `~/.zshrc`
To enable zsh tab-completion for velociraptor commands, add the following line to your `~/.zshrc`

```sh
source <(vr completions zsh)
```

Trigger the autocomplete on `vr`/`vr run` to get the available scripts as suggestions.

> Bash completions are not supported yet, but will be added.
> Bash is not supported yet, but will be added.
## Known limitations

Expand All @@ -314,7 +397,6 @@ As a workaround you can tell Velociraptor to use `PowerShell` instead of `cmd` (
## Upcoming features

- [ ] Self-update: run `vr upgrade` to install the latest version.
- [ ] Scripts exporting: run `vr export` to save your scripts as shell scripts to avoid having to install `vr` in your production environment.
- [ ] Husky style git hooks: use the `hook` property to link a script to a git hook.

## Contributing
Expand Down
1 change: 1 addition & 0 deletions assets/logo.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 13 additions & 10 deletions deps.ts
@@ -1,19 +1,22 @@
export { stringSimilarity } from "https://unpkg.com/string-similarity-js@2.1.2/src/string-similarity.ts";
export { parse as parseYaml } from "https://deno.land/std@v0.42.0/encoding/yaml.ts";
export { readJsonSync } from "https://deno.land/std@v0.42.0/fs/read_json.ts";
export { readFileStrSync } from "https://deno.land/std@v0.42.0/fs/read_file_str.ts";
export { existsSync } from "https://deno.land/std@v0.42.0/fs/exists.ts";
export * as path from "https://deno.land/std@v0.42.0/path/mod.ts";
export * as logger from "https://deno.land/std@v0.42.0/log/mod.ts";
export { default as levenshtein } from "https://deno.land/x/levenshtein@v1.0.0/mod.ts";
export { parse as parseYaml } from "https://deno.land/std@v0.52.0/encoding/yaml.ts";
export { readFileStrSync } from "https://deno.land/std@v0.52.0/fs/read_file_str.ts";
export { writeFileStr } from "https://deno.land/std@v0.52.0/fs/write_file_str.ts";
export { moveSync } from "https://deno.land/std@v0.52.0/fs/move.ts";
export { existsSync } from "https://deno.land/std@v0.52.0/fs/exists.ts";
export { ensureDirSync } from "https://deno.land/std@v0.52.0/fs/ensure_dir.ts";
export * as path from "https://deno.land/std@v0.52.0/path/mod.ts";
export * as logger from "https://deno.land/std@v0.52.0/log/mod.ts";
export {
blue,
yellow,
red,
bold,
gray,
} from "https://deno.land/std@v0.42.0/fmt/colors.ts";
export { ConsoleHandler } from "https://deno.land/std@v0.42.0/log/handlers.ts";
export { LogRecord } from "https://deno.land/std@v0.42.0/log/logger.ts";
} from "https://deno.land/std@v0.52.0/fmt/colors.ts";
export { ConsoleHandler } from "https://deno.land/std@v0.52.0/log/handlers.ts";
export { LogRecord } from "https://deno.land/std@v0.52.0/log/logger.ts";
export { LevelName } from "https://deno.land/std@v0.52.0/log/levels.ts";
export {
Command,
BaseCommand,
Expand Down
114 changes: 114 additions & 0 deletions src/build_command_string.ts
@@ -0,0 +1,114 @@
import { Command } from "./command.ts";
import { FlagsObject, ScriptOptions } from "./scripts_config.ts";

const denoCmdOptions: { [key: string]: string[] } = {
bundle: ["cert", "imap", "log"],
cache: ["cert", "tsconfig", "imap", "lock", "log"],
install: ["allow", "log"],
run: [
"allow",
"cert",
"tsconfig",
"imap",
"inspect",
"inspectBrk",
"lock",
"log",
"v8Flags",
],
test: [
"allow",
"cert",
"tsconfig",
"imap",
"inspect",
"inspectBrk",
"lock",
"log",
"v8Flags",
],
};

const denoOption: { [key: string]: string } = {
allow: "allow-",
cert: "cert",
imap: "importmap",
inspect: "inspect",
inspectBrk: "inspect-brk",
lock: "lock",
log: "log-level",
tsconfig: "config",
v8Flags: "v8-flags",
};

export function buildCommandString(command: Command): string {
let cmd = command.cmd.concat(), match;
if (match = matchCompactRun(cmd)) {
cmd = "deno run " + cmd;
}
if (match = matchDenoCommand(cmd)) {
const subCommand = match[1];
if (subCommand && subCommand in denoCmdOptions) {
const insertAt = match[0].length;
const options = denoCmdOptions[subCommand];
for (let optionName of options) {
const option = command[optionName as keyof ScriptOptions];
if (option) {
if (optionName === "allow") {
const flags = generateFlagOptions(
option as FlagsObject,
denoOption[optionName],
);
if (flags && flags.length > 0) {
cmd = insertOptions(cmd, insertAt, ...flags);
}
} else if (optionName === "v8Flags") {
const flags = generateFlagOptions(option as FlagsObject);
if (flags && flags.length > 0) {
cmd = insertOptions(
cmd,
insertAt,
`--${denoOption[optionName]}=${flags.join(",")}`,
);
}
} else {
cmd = insertOptions(
cmd,
insertAt,
`--${denoOption[optionName]}=${option}`,
);
}
}
}
}
}
return cmd;
}

function insertOptions(
command: string,
atPosition: number,
...options: string[]
) {
return command.slice(0, atPosition) + " " + options.join(" ") +
command.slice(atPosition);
}

function generateFlagOptions(
flags: FlagsObject,
prefix: string = "",
): string[] {
return Object.entries(flags).map(([k, v]) =>
`--${prefix}${k}${v !== true ? `="${v}"` : ""}`
);
}

function matchDenoCommand(command: string) {
return command.match(/^deno +(\w+)/);
}

function matchCompactRun(command: string) {
return command.match(
/^'(?:\\'|.)*?\.ts'|^"(?:\\"|.)*?\.ts"|^(?:\\\ |\S)+\.ts/,
);
}

0 comments on commit 399d5e3

Please sign in to comment.