aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Fran Zekan <zekan.fran369@gmail.com> 2023-03-04 02:49:32 +0100
committerGravatar GitHub <noreply@github.com> 2023-03-03 17:49:32 -0800
commit7c367ff687554c39baf1d27218c9c8bc7129650b (patch)
tree41ac0661ffa2d5fc3a6de7591551d5e3b64185bc
parent0f8f484e21e3ebafaf62370421f6296eaca262fe (diff)
downloadbun-7c367ff687554c39baf1d27218c9c8bc7129650b.tar.gz
bun-7c367ff687554c39baf1d27218c9c8bc7129650b.tar.zst
bun-7c367ff687554c39baf1d27218c9c8bc7129650b.zip
fix(bunx): Show usage when calling bunx without arguments (#2295)
* Make sure to return a helpful error message if no args are passed to bunx * Add tests for bunx without args
-rw-r--r--src/cli/bunx_command.zig43
-rw-r--r--test/bun.js/install/bunx.test.ts19
2 files changed, 45 insertions, 17 deletions
diff --git a/src/cli/bunx_command.zig b/src/cli/bunx_command.zig
index ef1fc3c17..ef23757df 100644
--- a/src/cli/bunx_command.zig
+++ b/src/cli/bunx_command.zig
@@ -118,6 +118,25 @@ pub const BunxCommand = struct {
};
}
+ fn exit_with_usage() noreturn {
+ Output.prettyErrorln(
+ \\usage<r><d>:<r> <cyan>bunx <r><d>[<r><blue>--bun<r><d>]<r><cyan> package<r><d>[@version] [...flags or arguments to pass through]<r>
+ \\
+ \\bunx runs an npm package executable, automatically installing into a global shared cache if not installed in node_modules.
+ \\
+ \\example<d>:<r>
+ \\
+ \\ <cyan>bunx bun-repl<r>
+ \\ <cyan>bunx prettier foo.js<r>
+ \\
+ \\The <blue>--bun<r> flag forces the package to run in Bun's JavaScript runtime, even when it tries to use Node.js.
+ \\
+ \\ <cyan>bunx <r><blue>--bun<r><cyan> tsc --version<r>
+ \\
+ , .{});
+ Global.exit(1);
+ }
+
pub fn exec(ctx: bun.CLI.Command.Context) !void {
var requests_buf = bun.PackageManager.UpdateRequest.Array.init(0) catch unreachable;
var run_in_bun = ctx.debug.run_in_bun;
@@ -158,7 +177,10 @@ pub const BunxCommand = struct {
}
}
- const passthrough = passthrough_list.items;
+ // check if package_name_for_update_request is empty string or " "
+ if (package_name_for_update_request[0].len == 0) {
+ exit_with_usage();
+ }
var update_requests = bun.PackageManager.UpdateRequest.parse(
ctx.allocator,
@@ -169,22 +191,7 @@ pub const BunxCommand = struct {
);
if (update_requests.len == 0) {
- Output.prettyErrorln(
- \\usage<r><d>:<r> <cyan>bunx <r><d>[<r><blue>--bun<r><d>]<r><cyan> package<r><d>[@version] [...flags or arguments to pass through]<r>
- \\
- \\bunx runs an npm package executable, automatically installing into a global shared cache if not installed in node_modules.
- \\
- \\example<d>:<r>
- \\
- \\ <cyan>bunx bun-repl<r>
- \\ <cyan>bunx prettier foo.js<r>
- \\
- \\The <blue>--bun<r> flag forces the package to run in Bun's JavaScript runtime, even when it tries to use Node.js.
- \\
- \\ <cyan>bunx <r><blue>--bun<r><cyan> tsc --version<r>
- \\
- , .{});
- Global.exit(1);
+ exit_with_usage();
}
// this shouldn't happen
@@ -248,6 +255,8 @@ pub const BunxCommand = struct {
var absolute_in_cache_dir_buf: [bun.MAX_PATH_BYTES]u8 = undefined;
var absolute_in_cache_dir = std.fmt.bufPrint(&absolute_in_cache_dir_buf, "/{s}/node_modules/.bin/{s}", .{ bunx_cache_dir, initial_bin_name }) catch unreachable;
+ const passthrough = passthrough_list.items;
+
// Similar to "npx":
//
// 1. Try the bin in the current node_modules and then we try the bin in the global cache
diff --git a/test/bun.js/install/bunx.test.ts b/test/bun.js/install/bunx.test.ts
index 76cd944a1..941f006bb 100644
--- a/test/bun.js/install/bunx.test.ts
+++ b/test/bun.js/install/bunx.test.ts
@@ -53,6 +53,25 @@ it("should install and run specified version", async () => {
expect(await exited).toBe(0);
});
+it("should output usage if no arguments are passed", async () => {
+ const { stdout, stderr, exited } = spawn({
+ cmd: [bunExe(), "x"],
+ cwd: x_dir,
+ stdout: null,
+ stdin: "pipe",
+ stderr: "pipe",
+ env,
+ });
+
+ expect(stderr).toBeDefined();
+ const err = await new Response(stderr).text();
+ expect(err).toContain("usage: ");
+ expect(stdout).toBeDefined();
+ const out = await new Response(stdout).text();
+ expect(out).toHaveLength(0);
+ expect(await exited).toBe(1);
+});
+
it("should download dependency to run local file", async () => {
await writeFile(
join(x_dir, "test.js"),