Add --quiet flag to bun pm pack command (#21053)

Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: jarred-sumner-bot <220441119+jarred-sumner-bot@users.noreply.github.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
This commit is contained in:
jarred-sumner-bot
2025-07-15 01:14:58 -07:00
committed by GitHub
parent 89aae0bdc0
commit 803181ae7c
6 changed files with 105 additions and 11 deletions

View File

@@ -8,15 +8,70 @@ To create a tarball of the current workspace:
$ bun pm pack
```
Options for the `pack` command:
This command creates a `.tgz` file containing all files that would be published to npm, following the same rules as `npm pack`.
- `--dry-run`: Perform all tasks except writing the tarball to disk.
- `--destination`: Specify the directory where the tarball will be saved.
- `--filename`: Specify an exact file name for the tarball to be saved at.
## Examples
Basic usage:
```bash
$ bun pm pack
# Creates my-package-1.0.0.tgz in current directory
```
Quiet mode for scripting:
```bash
$ TARBALL=$(bun pm pack --quiet)
$ echo "Created: $TARBALL"
# Output: Created: my-package-1.0.0.tgz
```
Custom destination:
```bash
$ bun pm pack --destination ./dist
# Saves tarball in ./dist/ directory
```
## Options
- `--dry-run`: Perform all tasks except writing the tarball to disk. Shows what would be included.
- `--destination <dir>`: Specify the directory where the tarball will be saved.
- `--filename <name>`: Specify an exact file name for the tarball to be saved at.
- `--ignore-scripts`: Skip running pre/postpack and prepare scripts.
- `--gzip-level`: Set a custom compression level for gzip, ranging from 0 to 9 (default is 9).
- `--gzip-level <0-9>`: Set a custom compression level for gzip, ranging from 0 to 9 (default is 9).
- `--quiet`: Only output the tarball filename, suppressing verbose output. Ideal for scripts and automation.
> Note `--filename` and `--destination` cannot be used at the same time
> **Note:** `--filename` and `--destination` cannot be used at the same time.
## Output Modes
**Default output:**
```bash
$ bun pm pack
bun pack v1.2.19
packed 131B package.json
packed 40B index.js
my-package-1.0.0.tgz
Total files: 2
Shasum: f2451d6eb1e818f500a791d9aace80b394258a90
Unpacked size: 171B
Packed size: 249B
```
**Quiet output:**
```bash
$ bun pm pack --quiet
my-package-1.0.0.tgz
```
The `--quiet` flag is particularly useful for automation workflows where you need to capture the generated tarball filename for further processing.
## bin

View File

@@ -63,7 +63,7 @@ pub const PackCommand = struct {
maybe_integrity: ?[sha.SHA512.digest]u8,
log_level: LogLevel,
) void {
if (log_level != .silent) {
if (log_level != .silent and log_level != .quiet) {
Output.prettyln("\n<r><b><blue>Total files<r>: {d}", .{stats.total_files});
if (maybe_shasum) |shasum| {
Output.prettyln("<b><blue>Shasum<r>: {s}", .{std.fmt.bytesToHex(shasum, .lower)});
@@ -93,8 +93,10 @@ pub const PackCommand = struct {
};
pub fn execWithManager(ctx: Command.Context, manager: *PackageManager) !void {
Output.prettyln("<r><b>bun pack <r><d>v" ++ Global.package_json_version_with_sha ++ "<r>", .{});
Output.flush();
if (manager.options.log_level != .silent and manager.options.log_level != .quiet) {
Output.prettyln("<r><b>bun pack <r><d>v" ++ Global.package_json_version_with_sha ++ "<r>", .{});
Output.flush();
}
var lockfile: Lockfile = undefined;
const load_from_disk_result = lockfile.loadFromCwd(
@@ -2426,7 +2428,7 @@ pub const PackCommand = struct {
package_json_len: usize,
) void {
const root_dir = bun.FD.fromStdDir(root_dir_std);
if (ctx.manager.options.log_level == .silent) return;
if (ctx.manager.options.log_level == .silent or ctx.manager.options.log_level == .quiet) return;
const packed_fmt = "<r><b><cyan>packed<r> {} {s}";
if (comptime is_dry_run) {

View File

@@ -121,7 +121,8 @@ pub const PackageManagerCommand = struct {
\\ <d>├<r> <cyan>--destination<r> the directory the tarball will be saved in
\\ <d>├<r> <cyan>--filename<r> the name of the tarball
\\ <d>├<r> <cyan>--ignore-scripts<r> don't run pre/postpack and prepare scripts
\\ <d><r> <cyan>--gzip-level<r> specify a custom compression level for gzip (0-9, default is 9)
\\ <d><r> <cyan>--gzip-level<r> specify a custom compression level for gzip (0-9, default is 9)
\\ <d>└<r> <cyan>--quiet<r> only output the tarball filename
\\ <b><green>bun pm<r> <blue>bin<r> print the path to bin folder
\\ <d>└<r> <cyan>-g<r> print the <b>global<r> path to bin folder
\\ <b><green>bun pm<r> <blue>ls<r> list the dependency tree according to the current lockfile

View File

@@ -32,6 +32,7 @@ const shared_params = [_]ParamType{
clap.parseParam("--cache-dir <PATH> Store & load cached data from a specific directory path") catch unreachable,
clap.parseParam("--no-cache Ignore manifest cache entirely") catch unreachable,
clap.parseParam("--silent Don't log anything") catch unreachable,
clap.parseParam("--quiet Only show tarball name when packing") catch unreachable,
clap.parseParam("--verbose Excessively verbose logging") catch unreachable,
clap.parseParam("--no-progress Disable the progress bar") catch unreachable,
clap.parseParam("--no-summary Don't print a summary") catch unreachable,
@@ -168,6 +169,7 @@ dry_run: bool = false,
force: bool = false,
no_cache: bool = false,
silent: bool = false,
quiet: bool = false,
verbose: bool = false,
no_progress: bool = false,
no_verify: bool = false,
@@ -672,6 +674,7 @@ pub fn parse(allocator: std.mem.Allocator, comptime subcommand: Subcommand) !Com
cli.no_verify = args.flag("--no-verify");
cli.no_cache = args.flag("--no-cache");
cli.silent = args.flag("--silent");
cli.quiet = args.flag("--quiet");
cli.verbose = args.flag("--verbose") or Output.is_verbose;
cli.ignore_scripts = args.flag("--ignore-scripts");
cli.trusted = args.flag("--trust");

View File

@@ -101,6 +101,7 @@ pub const LogLevel = enum {
default,
verbose,
silent,
quiet,
default_no_progress,
verbose_no_progress,
@@ -511,6 +512,9 @@ pub fn load(
} else if (cli.silent) {
this.log_level = .silent;
PackageManager.verbose_install = false;
} else if (cli.quiet) {
this.log_level = .quiet;
PackageManager.verbose_install = false;
} else {
this.log_level = if (disable_progress_bar) LogLevel.default_no_progress else LogLevel.default;
PackageManager.verbose_install = false;

View File

@@ -394,6 +394,35 @@ describe("flags", () => {
expect(results).toEqual([true, true, false, true, false]);
});
test("--quiet", async () => {
await Promise.all([
write(
join(packageDir, "package.json"),
JSON.stringify({
name: "pack-quiet-test",
version: "1.1.1",
}),
),
write(join(packageDir, "index.js"), "console.log('hello ./index.js')"),
]);
const { out } = await pack(packageDir, bunEnv, "--quiet");
// Should not contain verbose output
expect(out).not.toContain("Total files:");
expect(out).not.toContain("Shasum:");
expect(out).not.toContain("Integrity:");
expect(out).not.toContain("Unpacked size:");
expect(out).not.toContain("Packed size:");
expect(out).not.toContain("bun pack v");
// Should only contain the tarball name
expect(out.trim()).toBe("pack-quiet-test-1.1.1.tgz");
// Should still create the tarball
expect(await exists(join(packageDir, "pack-quiet-test-1.1.1.tgz"))).toBeTrue();
});
});
test("shasum and integrity are consistent", async () => {