@vlandoss/run-run 0.3.0 → 0.3.1-git-f19fe37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -4
- package/bin +40 -0
- package/dist/cli.usage.kdl +71 -0
- package/dist/run.mjs +39 -28
- package/package.json +12 -11
- package/src/program/commands/completion.ts +26 -0
- package/src/program/commands/test-static.ts +1 -1
- package/src/program/commands/usage.ts +9 -0
- package/src/program/commands/x.ts +16 -0
- package/src/program/index.ts +29 -25
- package/src/program/ui.ts +2 -0
- package/src/run.ts +1 -2
- package/bin.mjs +0 -2
- package/src/program/commands/run.ts +0 -12
- package/src/program/parse-args.ts +0 -19
package/README.md
CHANGED
|
@@ -18,19 +18,42 @@ CLI toolbox to fullstack common scripts in Variable Land 👊
|
|
|
18
18
|
pnpm add @vlandoss/run-run
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
It
|
|
21
|
+
It adds the `rr` command to your project.
|
|
22
22
|
|
|
23
23
|
## Usage
|
|
24
24
|
|
|
25
|
-
> [!NOTE]
|
|
26
|
-
> The documentation is WIP
|
|
27
|
-
|
|
28
25
|
Run the help command:
|
|
29
26
|
|
|
30
27
|
```sh
|
|
31
28
|
rr help
|
|
32
29
|
```
|
|
33
30
|
|
|
31
|
+
See [`CLI.md`](./CLI.md) for the full reference (auto-generated per release).
|
|
32
|
+
|
|
33
|
+
## Shell completion
|
|
34
|
+
|
|
35
|
+
`rr` ships a `completion` subcommand that prints a shell-specific script. Add it to your shell rc file:
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
# zsh — ~/.zshrc
|
|
39
|
+
eval "$(rr completion zsh)"
|
|
40
|
+
|
|
41
|
+
# bash — ~/.bashrc
|
|
42
|
+
eval "$(rr completion bash)"
|
|
43
|
+
|
|
44
|
+
# fish — ~/.config/fish/config.fish
|
|
45
|
+
rr completion fish | source
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Prerequisite:** the [`usage`](https://usage.jdx.dev) CLI must be on your `PATH` (it powers completion at runtime). Install via one of:
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
mise use -g usage
|
|
52
|
+
brew install usage
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
When you upgrade `@vlandoss/run-run`, the next shell session will pick up new commands automatically — no need to re-run anything.
|
|
56
|
+
|
|
34
57
|
## Troubleshooting
|
|
35
58
|
|
|
36
59
|
To enable debug mode, set the `DEBUG` environment variable to `run-run:*` before running *any* command.
|
package/bin
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
SOURCE="${BASH_SOURCE[0]}"
|
|
5
|
+
while [ -L "$SOURCE" ]; do
|
|
6
|
+
TARGET="$(readlink "$SOURCE")"
|
|
7
|
+
case "$TARGET" in
|
|
8
|
+
/*) SOURCE="$TARGET" ;;
|
|
9
|
+
*) SOURCE="$(dirname "$SOURCE")/$TARGET" ;;
|
|
10
|
+
esac
|
|
11
|
+
done
|
|
12
|
+
DIR="$(cd "$(dirname "$SOURCE")" && pwd)"
|
|
13
|
+
|
|
14
|
+
if [ "$1" = "completion" ]; then
|
|
15
|
+
case "$2" in
|
|
16
|
+
bash | zsh | fish)
|
|
17
|
+
kdl="$DIR/dist/cli.usage.kdl"
|
|
18
|
+
if [ ! -f "$kdl" ]; then
|
|
19
|
+
echo "rr completion: missing $kdl. Reinstall @vlandoss/run-run or run \`pnpm build\`." >&2
|
|
20
|
+
exit 1
|
|
21
|
+
fi
|
|
22
|
+
if ! command -v usage >/dev/null 2>&1; then
|
|
23
|
+
echo "rr completion: 'usage' CLI not found in PATH." >&2
|
|
24
|
+
echo "Install via: mise use -g usage | brew install usage" >&2
|
|
25
|
+
exit 1
|
|
26
|
+
fi
|
|
27
|
+
exec usage generate completion "$2" rr --file "$kdl"
|
|
28
|
+
;;
|
|
29
|
+
esac
|
|
30
|
+
# Unknown shell or `--help`: fall through to Node so Commander prints help/errors.
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
# In the source repo (tsdown.config.ts present, NOT shipped in the npm tarball),
|
|
34
|
+
# always run from src/ so live edits show up. In a published install, use the
|
|
35
|
+
# bundled dist/run.mjs.
|
|
36
|
+
if [ -f "$DIR/tsdown.config.ts" ]; then
|
|
37
|
+
exec node "$DIR/src/run.ts" "$@"
|
|
38
|
+
else
|
|
39
|
+
exec node "$DIR/dist/run.mjs" "$@"
|
|
40
|
+
fi
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// @generated by @usage-spec/commander from Commander.js metadata
|
|
2
|
+
name rr
|
|
3
|
+
bin rr
|
|
4
|
+
version "0.3.1-git-f19fe37.0"
|
|
5
|
+
usage "[options] <command...>"
|
|
6
|
+
flag --usage help="print KDL spec for this CLI (https://kdl.dev)"
|
|
7
|
+
cmd completion help="print shell completion script 🐚 (usage)" {
|
|
8
|
+
long_help "Prints a shell completion script for rr. Add to your shell rc file:\n\n bash: eval \"$(rr completion bash)\"\n zsh: eval \"$(rr completion zsh)\"\n fish: rr completion fish | source"
|
|
9
|
+
arg <shell> help="target shell" {
|
|
10
|
+
choices bash zsh fish
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
cmd build:lib help="build a ts library 🏗️ (tsdown)" {
|
|
14
|
+
long_help "Compiles TypeScript code into JavaScript and generates type declaration files, making it ready for distribution."
|
|
15
|
+
cmd doctor help="check if the underlying tool is working correctly"
|
|
16
|
+
}
|
|
17
|
+
cmd jsc help="check format and lint 🔍 (biome)" {
|
|
18
|
+
alias jscheck check
|
|
19
|
+
long_help "Checks the code for formatting and linting issues, ensuring it adheres to the defined style and quality standards."
|
|
20
|
+
flag --fix help="try to fix issues automatically"
|
|
21
|
+
flag --fix-staged help="try to fix staged files only"
|
|
22
|
+
cmd doctor help="check if the underlying tool is working correctly"
|
|
23
|
+
}
|
|
24
|
+
cmd tsc help="check typescript errors 🧩 (tsc)" {
|
|
25
|
+
alias tscheck
|
|
26
|
+
long_help "Checks the TypeScript code for type errors, ensuring that the code adheres to the defined type constraints and helps catch potential issues before runtime."
|
|
27
|
+
cmd doctor help="check if the underlying tool is working correctly"
|
|
28
|
+
}
|
|
29
|
+
cmd lint help="check & fix lint errors 🔍 (biome)" {
|
|
30
|
+
long_help "Checks the code for linting issues and optionally fixes them, ensuring it adheres to the defined quality standards."
|
|
31
|
+
flag "-c --check" help="check if the code is valid" default=#true
|
|
32
|
+
flag --fix help="try to fix all the code"
|
|
33
|
+
cmd doctor help="check if the underlying tool is working correctly"
|
|
34
|
+
}
|
|
35
|
+
cmd format help="check & fix format errors 🎨 (biome)" {
|
|
36
|
+
long_help "Checks the code for formatting issues and optionally fixes them, ensuring it adheres to the defined style standards."
|
|
37
|
+
flag --fix help="format all the code"
|
|
38
|
+
cmd doctor help="check if the underlying tool is working correctly"
|
|
39
|
+
}
|
|
40
|
+
cmd test:static help="run static tests 🔬 (run-run)" {
|
|
41
|
+
long_help "Runs static tests, including linting, formatting checks, and TypeScript type checking, to ensure code quality and correctness without executing the code."
|
|
42
|
+
}
|
|
43
|
+
cmd clean help="delete dirty files 🗑️ (rimraf)" {
|
|
44
|
+
long_help "Deletes generated files and folders such as 'dist', 'node_modules', and lock files to ensure a clean state."
|
|
45
|
+
flag --only-dist help="delete 'dist' folders only"
|
|
46
|
+
flag --dry-run help="outputs the paths that would be deleted"
|
|
47
|
+
}
|
|
48
|
+
cmd pkgs help="list affected packages 📦" {
|
|
49
|
+
long_help "Given a list of files, returns the list of affected packages. Useful to run commands only on affected packages."
|
|
50
|
+
flag --files help="list of files to check" var=#true {
|
|
51
|
+
arg <FILES>
|
|
52
|
+
}
|
|
53
|
+
flag --decorator help="type of decorator to use" {
|
|
54
|
+
arg <DECORATOR> {
|
|
55
|
+
choices turbo
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
cmd x help="run multiple rr subcommands concurrently" {
|
|
60
|
+
long_help "Run multiple rr subcommands concurrently (e.g. `rr x jsc tsc`)."
|
|
61
|
+
arg <cmds>… help="rr subcommands to execute concurrently" var=#true
|
|
62
|
+
}
|
|
63
|
+
cmd config help="display the current config 🛠️" {
|
|
64
|
+
long_help "Displays the current configuration settings, including their source file path if available."
|
|
65
|
+
}
|
|
66
|
+
cmd tools hide=#true subcommand_required=#true help="expose the internal tools 🛠️" {
|
|
67
|
+
cmd biome
|
|
68
|
+
cmd oxfmt
|
|
69
|
+
cmd oxlint
|
|
70
|
+
cmd tsdown
|
|
71
|
+
}
|
package/dist/run.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { colorIsSupported, colorize, createPkgService, createShellService, cwd, dirnameOf, getVersion, palette, run } from "@vlandoss/clibuddy";
|
|
4
|
-
import { Option, createCommand } from "commander";
|
|
4
|
+
import { Argument, Option, createCommand } from "commander";
|
|
5
5
|
import fs from "node:fs";
|
|
6
6
|
import os from "node:os";
|
|
7
7
|
import { lilconfig } from "lilconfig";
|
|
@@ -10,6 +10,7 @@ import memoize from "memoize";
|
|
|
10
10
|
import { glob } from "glob";
|
|
11
11
|
import { rimraf } from "rimraf";
|
|
12
12
|
import isCI from "is-ci";
|
|
13
|
+
import { generateToStdout } from "@usage-spec/commander";
|
|
13
14
|
//#region \0rolldown/runtime.js
|
|
14
15
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
15
16
|
//#endregion
|
|
@@ -95,6 +96,7 @@ const oxfmtColor = colorize("#32F3E9");
|
|
|
95
96
|
const tscColor = colorize("#3178C6");
|
|
96
97
|
const rimrafColor = colorize("#7C7270");
|
|
97
98
|
const runRunColor = colorize("FC7A1E");
|
|
99
|
+
const usageColor = colorize("#24C55E");
|
|
98
100
|
const TOOL_LABELS = {
|
|
99
101
|
TSDOWN: tsdownColor("tsdown"),
|
|
100
102
|
BIOME: biomeColor("biome"),
|
|
@@ -102,7 +104,8 @@ const TOOL_LABELS = {
|
|
|
102
104
|
OXFMT: oxfmtColor("oxfmt"),
|
|
103
105
|
TSC: tscColor("tsc"),
|
|
104
106
|
RIMRAF: rimrafColor("rimraf"),
|
|
105
|
-
RUN_RUN: runRunColor("run-run")
|
|
107
|
+
RUN_RUN: runRunColor("run-run"),
|
|
108
|
+
USAGE: usageColor("usage")
|
|
106
109
|
};
|
|
107
110
|
function getBannerText(version) {
|
|
108
111
|
const uiLogo = `🦊 ${palette.bold("R")} ${palette.bold("U")} ${palette.bold("N")} - ${palette.bold("R")} ${palette.bold("U")} ${palette.bold("N")}`;
|
|
@@ -342,6 +345,21 @@ function createCleanCommand() {
|
|
|
342
345
|
}).addHelpText("afterAll", `\nUnder the hood, this command uses ${TOOL_LABELS.RIMRAF} to delete dirty folders or files.`);
|
|
343
346
|
}
|
|
344
347
|
//#endregion
|
|
348
|
+
//#region src/program/commands/completion.ts
|
|
349
|
+
const SHELLS = [
|
|
350
|
+
"bash",
|
|
351
|
+
"zsh",
|
|
352
|
+
"fish"
|
|
353
|
+
];
|
|
354
|
+
function createCompletionCommand() {
|
|
355
|
+
return createCommand("completion").summary(`print shell completion script 🐚 (${TOOL_LABELS.USAGE})`).description(`Prints a shell completion script for rr. Add to your shell rc file:
|
|
356
|
+
|
|
357
|
+
bash: eval "$(rr completion bash)"
|
|
358
|
+
zsh: eval "$(rr completion zsh)"
|
|
359
|
+
fish: rr completion fish | source`).addArgument(new Argument("<shell>", `target shell`).choices(SHELLS)).addHelpText("afterAll", `\nUnder the hood, this command uses ${TOOL_LABELS.USAGE} (https://usage.jdx.dev).
|
|
360
|
+
Make sure to have it installed and available in your PATH.`);
|
|
361
|
+
}
|
|
362
|
+
//#endregion
|
|
345
363
|
//#region src/program/commands/config.ts
|
|
346
364
|
function createConfigCommand(ctx) {
|
|
347
365
|
return createCommand("config").summary("display the current config 🛠️").description("Displays the current configuration settings, including their source file path if available.").action(async function configAction() {
|
|
@@ -489,19 +507,10 @@ function createPkgsCommand(ctx) {
|
|
|
489
507
|
});
|
|
490
508
|
}
|
|
491
509
|
//#endregion
|
|
492
|
-
//#region src/program/commands/run.ts
|
|
493
|
-
function createRunCommand(ctx) {
|
|
494
|
-
return createCommand("run").argument("<cmds...>", "commands to execute concurrently (e.g. 'check tsc')").action(async function runRunAction(cmds) {
|
|
495
|
-
const { $ } = ctx.shell;
|
|
496
|
-
const commands = cmds.map((cmd) => $`rr ${cmd}`);
|
|
497
|
-
await Promise.all(commands);
|
|
498
|
-
});
|
|
499
|
-
}
|
|
500
|
-
//#endregion
|
|
501
510
|
//#region src/program/commands/test-static.ts
|
|
502
511
|
function createTestStaticCommand(ctx) {
|
|
503
512
|
return createCommand("test:static").summary(`run static tests 🔬 (${TOOL_LABELS.RUN_RUN})`).description("Runs static tests, including linting, formatting checks, and TypeScript type checking, to ensure code quality and correctness without executing the code.").action(async function testStaticAction() {
|
|
504
|
-
await ctx.shell.$`rr jscheck tscheck`;
|
|
513
|
+
await ctx.shell.$`rr x jscheck tscheck`;
|
|
505
514
|
});
|
|
506
515
|
}
|
|
507
516
|
//#endregion
|
|
@@ -603,35 +612,37 @@ function createTsCheckCommand(ctx) {
|
|
|
603
612
|
});
|
|
604
613
|
}
|
|
605
614
|
//#endregion
|
|
615
|
+
//#region src/program/commands/usage.ts
|
|
616
|
+
function addUsage(program) {
|
|
617
|
+
return program.addOption(new Option("--usage", "print KDL spec for this CLI (https://kdl.dev)")).on("option:usage", () => {
|
|
618
|
+
generateToStdout(program);
|
|
619
|
+
process.exit(0);
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
//#endregion
|
|
623
|
+
//#region src/program/commands/x.ts
|
|
624
|
+
function createXCommand(ctx) {
|
|
625
|
+
return createCommand("x").summary("run multiple rr subcommands concurrently").description("Run multiple rr subcommands concurrently (e.g. `rr x jsc tsc`).").argument("<cmds...>", "rr subcommands to execute concurrently").action(async function runXAction(cmds) {
|
|
626
|
+
const { $ } = ctx.shell;
|
|
627
|
+
if ((await Promise.allSettled(cmds.map((cmd) => $`rr ${cmd}`))).some((r) => r.status === "rejected")) process.exitCode = 1;
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
//#endregion
|
|
606
631
|
//#region src/program/index.ts
|
|
607
632
|
async function createProgram(options) {
|
|
608
633
|
const ctx = await createContext(options.binDir);
|
|
609
634
|
const version = getVersion(ctx.binPkg);
|
|
610
635
|
return {
|
|
611
|
-
program: createCommand("rr").
|
|
636
|
+
program: addUsage(createCommand("rr").usage("[options] <command...>").version(version, "-v, --version").addHelpText("before", getBannerText(version)).addHelpText("after", CREDITS_TEXT).addCommand(createCompletionCommand()).addCommand(createBuildLibCommand(ctx)).addCommand(createJsCheckCommand(ctx)).addCommand(createTsCheckCommand(ctx)).addCommand(createLintCommand(ctx)).addCommand(createFormatCommand(ctx)).addCommand(createTestStaticCommand(ctx)).addCommand(createCleanCommand()).addCommand(createPkgsCommand(ctx)).addCommand(createXCommand(ctx)).addCommand(createConfigCommand(ctx)).addCommand(createToolsCommand(ctx), { hidden: true })),
|
|
612
637
|
ctx
|
|
613
638
|
};
|
|
614
639
|
}
|
|
615
640
|
//#endregion
|
|
616
|
-
//#region src/program/parse-args.ts
|
|
617
|
-
const debug = logger.subdebug("parseArgs");
|
|
618
|
-
function parseArgs(argv = process.argv) {
|
|
619
|
-
const args = argv.slice(2);
|
|
620
|
-
const lastArg = args[args.length - 1];
|
|
621
|
-
const allArgsAreValidCommands = args.every((arg) => !arg.startsWith("-")) && args.length > 1 && args[0] !== "tools" && lastArg !== "doctor";
|
|
622
|
-
debug("args %O", args);
|
|
623
|
-
if (allArgsAreValidCommands) {
|
|
624
|
-
debug("multiple commands detected, adding 'run' command");
|
|
625
|
-
return ["run", ...args];
|
|
626
|
-
}
|
|
627
|
-
return args;
|
|
628
|
-
}
|
|
629
|
-
//#endregion
|
|
630
641
|
//#region src/run.ts
|
|
631
642
|
const BIN_DIR = path.dirname(dirnameOf(import.meta));
|
|
632
643
|
await run(async () => {
|
|
633
644
|
const { program } = await createProgram({ binDir: BIN_DIR });
|
|
634
|
-
await program.parseAsync(
|
|
645
|
+
await program.parseAsync(process.argv, { from: "node" });
|
|
635
646
|
}, logger);
|
|
636
647
|
//#endregion
|
|
637
648
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vlandoss/run-run",
|
|
3
|
-
"version": "0.3.0",
|
|
3
|
+
"version": "0.3.1-git-f19fe37.0",
|
|
4
4
|
"description": "The CLI toolbox to fullstack common scripts in Variable Land",
|
|
5
5
|
"homepage": "https://github.com/variableland/dx/tree/main/packages/run-run#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -29,15 +29,14 @@
|
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
31
|
"bin": {
|
|
32
|
-
"rr": "./bin
|
|
33
|
-
"run-run": "./bin.mjs",
|
|
32
|
+
"rr": "./bin",
|
|
34
33
|
"biome": "./tools/biome",
|
|
35
34
|
"oxfmt": "./tools/oxfmt",
|
|
36
35
|
"oxlint": "./tools/oxlint",
|
|
37
36
|
"tsdown": "./tools/tsdown"
|
|
38
37
|
},
|
|
39
38
|
"files": [
|
|
40
|
-
"bin
|
|
39
|
+
"bin",
|
|
41
40
|
"dist",
|
|
42
41
|
"src",
|
|
43
42
|
"!src/**/__tests__",
|
|
@@ -45,8 +44,15 @@
|
|
|
45
44
|
"tools",
|
|
46
45
|
"tsconfig.json"
|
|
47
46
|
],
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"access": "public"
|
|
49
|
+
},
|
|
50
|
+
"engines": {
|
|
51
|
+
"node": ">=20.0.0"
|
|
52
|
+
},
|
|
48
53
|
"dependencies": {
|
|
49
54
|
"@biomejs/biome": "2.4.4",
|
|
55
|
+
"@usage-spec/commander": "1.1.0",
|
|
50
56
|
"commander": "14.0.3",
|
|
51
57
|
"glob": "13.0.6",
|
|
52
58
|
"is-ci": "4.1.0",
|
|
@@ -61,17 +67,12 @@
|
|
|
61
67
|
"@vlandoss/clibuddy": "0.3.0",
|
|
62
68
|
"@vlandoss/loggy": "0.2.0"
|
|
63
69
|
},
|
|
64
|
-
"publishConfig": {
|
|
65
|
-
"access": "public"
|
|
66
|
-
},
|
|
67
|
-
"engines": {
|
|
68
|
-
"node": ">=20.0.0"
|
|
69
|
-
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@vlandoss/tsdown-config": "^0.0.1"
|
|
72
72
|
},
|
|
73
73
|
"scripts": {
|
|
74
|
-
"build": "tsdown",
|
|
74
|
+
"build": "tsdown && pnpm build:kdl",
|
|
75
|
+
"build:kdl": "./bin --usage > dist/cli.usage.kdl",
|
|
75
76
|
"test": "vitest run",
|
|
76
77
|
"test:unit": "vitest run --project unit",
|
|
77
78
|
"test:integration": "vitest run --project integration",
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Argument, createCommand } from "commander";
|
|
2
|
+
import { TOOL_LABELS } from "../ui.ts";
|
|
3
|
+
|
|
4
|
+
const SHELLS = ["bash", "zsh", "fish"] as const;
|
|
5
|
+
|
|
6
|
+
// Ghost command: registered with Commander purely for discoverability — it surfaces
|
|
7
|
+
// in `rr --help` and is baked into dist/cli.usage.kdl so the completion itself can
|
|
8
|
+
// suggest "completion" after `rr <TAB>`. The actual handler lives in the bash bin
|
|
9
|
+
// dispatcher, which intercepts `rr completion <shell>` before reaching Node.
|
|
10
|
+
export function createCompletionCommand() {
|
|
11
|
+
return createCommand("completion")
|
|
12
|
+
.summary(`print shell completion script 🐚 (${TOOL_LABELS.USAGE})`)
|
|
13
|
+
.description(
|
|
14
|
+
`Prints a shell completion script for rr. Add to your shell rc file:
|
|
15
|
+
|
|
16
|
+
bash: eval "$(rr completion bash)"
|
|
17
|
+
zsh: eval "$(rr completion zsh)"
|
|
18
|
+
fish: rr completion fish | source`,
|
|
19
|
+
)
|
|
20
|
+
.addArgument(new Argument("<shell>", `target shell`).choices(SHELLS))
|
|
21
|
+
.addHelpText(
|
|
22
|
+
"afterAll",
|
|
23
|
+
`\nUnder the hood, this command uses ${TOOL_LABELS.USAGE} (https://usage.jdx.dev).
|
|
24
|
+
Make sure to have it installed and available in your PATH.`,
|
|
25
|
+
);
|
|
26
|
+
}
|
|
@@ -9,6 +9,6 @@ export function createTestStaticCommand(ctx: Context) {
|
|
|
9
9
|
"Runs static tests, including linting, formatting checks, and TypeScript type checking, to ensure code quality and correctness without executing the code.",
|
|
10
10
|
)
|
|
11
11
|
.action(async function testStaticAction() {
|
|
12
|
-
await ctx.shell.$`rr jscheck tscheck`;
|
|
12
|
+
await ctx.shell.$`rr x jscheck tscheck`;
|
|
13
13
|
});
|
|
14
14
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { generateToStdout } from "@usage-spec/commander";
|
|
2
|
+
import { type Command, Option } from "commander";
|
|
3
|
+
|
|
4
|
+
export function addUsage(program: Command) {
|
|
5
|
+
return program.addOption(new Option("--usage", "print KDL spec for this CLI (https://kdl.dev)")).on("option:usage", () => {
|
|
6
|
+
generateToStdout(program);
|
|
7
|
+
process.exit(0);
|
|
8
|
+
});
|
|
9
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { createCommand } from "commander";
|
|
2
|
+
import type { Context } from "#src/services/ctx.ts";
|
|
3
|
+
|
|
4
|
+
export function createXCommand(ctx: Context) {
|
|
5
|
+
return createCommand("x")
|
|
6
|
+
.summary("run multiple rr subcommands concurrently")
|
|
7
|
+
.description("Run multiple rr subcommands concurrently (e.g. `rr x jsc tsc`).")
|
|
8
|
+
.argument("<cmds...>", "rr subcommands to execute concurrently")
|
|
9
|
+
.action(async function runXAction(cmds: string[]) {
|
|
10
|
+
const { $ } = ctx.shell;
|
|
11
|
+
const results = await Promise.allSettled(cmds.map((cmd) => $`rr ${cmd}`));
|
|
12
|
+
if (results.some((r) => r.status === "rejected")) {
|
|
13
|
+
process.exitCode = 1;
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
}
|
package/src/program/index.ts
CHANGED
|
@@ -3,15 +3,17 @@ import { createCommand } from "commander";
|
|
|
3
3
|
import { createContext } from "#src/services/ctx.ts";
|
|
4
4
|
import { createBuildLibCommand } from "./commands/build-lib.ts";
|
|
5
5
|
import { createCleanCommand } from "./commands/clean.ts";
|
|
6
|
+
import { createCompletionCommand } from "./commands/completion.ts";
|
|
6
7
|
import { createConfigCommand } from "./commands/config.ts";
|
|
7
8
|
import { createFormatCommand } from "./commands/format.ts";
|
|
8
9
|
import { createJsCheckCommand } from "./commands/jscheck.ts";
|
|
9
10
|
import { createLintCommand } from "./commands/lint.ts";
|
|
10
11
|
import { createPkgsCommand } from "./commands/pkgs.ts";
|
|
11
|
-
import { createRunCommand } from "./commands/run.ts";
|
|
12
12
|
import { createTestStaticCommand } from "./commands/test-static.ts";
|
|
13
13
|
import { createToolsCommand } from "./commands/tools.ts";
|
|
14
14
|
import { createTsCheckCommand } from "./commands/tscheck.ts";
|
|
15
|
+
import { addUsage } from "./commands/usage.ts";
|
|
16
|
+
import { createXCommand } from "./commands/x.ts";
|
|
15
17
|
import { CREDITS_TEXT, getBannerText } from "./ui.ts";
|
|
16
18
|
|
|
17
19
|
export type Options = {
|
|
@@ -22,30 +24,32 @@ export async function createProgram(options: Options) {
|
|
|
22
24
|
const ctx = await createContext(options.binDir);
|
|
23
25
|
const version = getVersion(ctx.binPkg);
|
|
24
26
|
|
|
25
|
-
const program =
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
27
|
+
const program = addUsage(
|
|
28
|
+
createCommand("rr")
|
|
29
|
+
.usage("[options] <command...>")
|
|
30
|
+
.version(version, "-v, --version")
|
|
31
|
+
.addHelpText("before", getBannerText(version))
|
|
32
|
+
.addHelpText("after", CREDITS_TEXT)
|
|
33
|
+
// completion
|
|
34
|
+
.addCommand(createCompletionCommand())
|
|
35
|
+
// build
|
|
36
|
+
.addCommand(createBuildLibCommand(ctx))
|
|
37
|
+
// check
|
|
38
|
+
.addCommand(createJsCheckCommand(ctx))
|
|
39
|
+
.addCommand(createTsCheckCommand(ctx))
|
|
40
|
+
.addCommand(createLintCommand(ctx))
|
|
41
|
+
.addCommand(createFormatCommand(ctx))
|
|
42
|
+
// test
|
|
43
|
+
.addCommand(createTestStaticCommand(ctx))
|
|
44
|
+
// misc
|
|
45
|
+
.addCommand(createCleanCommand())
|
|
46
|
+
.addCommand(createPkgsCommand(ctx))
|
|
47
|
+
.addCommand(createXCommand(ctx))
|
|
48
|
+
// config
|
|
49
|
+
.addCommand(createConfigCommand(ctx))
|
|
50
|
+
// hidden
|
|
51
|
+
.addCommand(createToolsCommand(ctx), { hidden: true }),
|
|
52
|
+
);
|
|
49
53
|
|
|
50
54
|
return { program, ctx };
|
|
51
55
|
}
|
package/src/program/ui.ts
CHANGED
|
@@ -14,6 +14,7 @@ const oxfmtColor = colorize("#32F3E9");
|
|
|
14
14
|
const tscColor = colorize("#3178C6");
|
|
15
15
|
const rimrafColor = colorize("#7C7270");
|
|
16
16
|
const runRunColor = colorize("FC7A1E");
|
|
17
|
+
const usageColor = colorize("#24C55E");
|
|
17
18
|
|
|
18
19
|
export const TOOL_LABELS = {
|
|
19
20
|
TSDOWN: tsdownColor("tsdown"),
|
|
@@ -23,6 +24,7 @@ export const TOOL_LABELS = {
|
|
|
23
24
|
TSC: tscColor("tsc"),
|
|
24
25
|
RIMRAF: rimrafColor("rimraf"),
|
|
25
26
|
RUN_RUN: runRunColor("run-run"),
|
|
27
|
+
USAGE: usageColor("usage"),
|
|
26
28
|
};
|
|
27
29
|
|
|
28
30
|
export function getBannerText(version: string) {
|
package/src/run.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { dirnameOf, run } from "@vlandoss/clibuddy";
|
|
3
3
|
import { createProgram } from "./program/index.ts";
|
|
4
|
-
import { parseArgs } from "./program/parse-args.ts";
|
|
5
4
|
import { logger } from "./services/logger.ts";
|
|
6
5
|
|
|
7
6
|
const BIN_DIR = path.dirname(dirnameOf(import.meta));
|
|
8
7
|
|
|
9
8
|
await run(async () => {
|
|
10
9
|
const { program } = await createProgram({ binDir: BIN_DIR });
|
|
11
|
-
await program.parseAsync(
|
|
10
|
+
await program.parseAsync(process.argv, { from: "node" });
|
|
12
11
|
}, logger);
|
package/bin.mjs
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { createCommand } from "commander";
|
|
2
|
-
import type { Context } from "#src/services/ctx.ts";
|
|
3
|
-
|
|
4
|
-
export function createRunCommand(ctx: Context) {
|
|
5
|
-
return createCommand("run")
|
|
6
|
-
.argument("<cmds...>", "commands to execute concurrently (e.g. 'check tsc')")
|
|
7
|
-
.action(async function runRunAction(cmds: string[]) {
|
|
8
|
-
const { $ } = ctx.shell;
|
|
9
|
-
const commands = cmds.map((cmd) => $`rr ${cmd}`);
|
|
10
|
-
await Promise.all(commands);
|
|
11
|
-
});
|
|
12
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { logger } from "../services/logger.ts";
|
|
2
|
-
|
|
3
|
-
const debug = logger.subdebug("parseArgs");
|
|
4
|
-
|
|
5
|
-
export function parseArgs(argv = process.argv) {
|
|
6
|
-
const args = argv.slice(2);
|
|
7
|
-
const lastArg = args[args.length - 1];
|
|
8
|
-
const allArgsAreValidCommands =
|
|
9
|
-
args.every((arg) => !arg.startsWith("-")) && args.length > 1 && args[0] !== "tools" && lastArg !== "doctor";
|
|
10
|
-
|
|
11
|
-
debug("args %O", args);
|
|
12
|
-
|
|
13
|
-
if (allArgsAreValidCommands) {
|
|
14
|
-
debug("multiple commands detected, adding 'run' command");
|
|
15
|
-
return ["run", ...args];
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return args;
|
|
19
|
-
}
|