Skip to main content

aft/compress/
pnpm.rs

1use crate::compress::generic::GenericCompressor;
2use crate::compress::Compressor;
3
4pub struct PnpmCompressor;
5
6impl Compressor for PnpmCompressor {
7    fn matches(&self, command: &str) -> bool {
8        command
9            .split_whitespace()
10            .next()
11            .is_some_and(|head| head == "pnpm")
12    }
13
14    fn compress(&self, command: &str, output: &str) -> String {
15        match pnpm_subcommand(command).as_deref() {
16            Some("install" | "i" | "add" | "remove") => compress_package(output),
17            Some("run" | "test" | "build") => GenericCompressor::compress_output(output),
18            _ => GenericCompressor::compress_output(output),
19        }
20    }
21}
22
23fn pnpm_subcommand(command: &str) -> Option<String> {
24    command
25        .split_whitespace()
26        .skip_while(|token| *token != "pnpm")
27        .skip(1)
28        .find(|token| !token.starts_with('-'))
29        .map(ToString::to_string)
30}
31
32fn compress_package(output: &str) -> String {
33    let mut result = Vec::new();
34    let mut progress_seen = 0usize;
35    let mut up_to_date_seen = false;
36
37    for line in output.lines() {
38        let trimmed = line.trim_start();
39        if trimmed.starts_with("Progress: resolved ") {
40            progress_seen += 1;
41            if progress_seen > 2 {
42                continue;
43            }
44        }
45        if trimmed == "Already up-to-date" {
46            if up_to_date_seen {
47                continue;
48            }
49            up_to_date_seen = true;
50        }
51        if trimmed.contains("WARN GET_NO_AUTH")
52            || trimmed.starts_with("ERR_PNPM_")
53            || trimmed.starts_with("Progress: resolved ")
54            || trimmed == "Already up-to-date"
55            || trimmed.starts_with("dependencies:")
56            || trimmed.starts_with("devDependencies:")
57            || trimmed.starts_with("Done in ")
58        {
59            result.push(line.to_string());
60        }
61    }
62
63    trim_trailing_lines(&result.join("\n"))
64}
65
66fn trim_trailing_lines(input: &str) -> String {
67    input
68        .lines()
69        .map(str::trim_end)
70        .collect::<Vec<_>>()
71        .join("\n")
72}