Skip to content

refactor(pm-cli): consolidate package manager infrastructure#2140

Draft
forehalo wants to merge 1 commit into
voidzero-dev:mainfrom
forehalo:refactor/cli
Draft

refactor(pm-cli): consolidate package manager infrastructure#2140
forehalo wants to merge 1 commit into
voidzero-dev:mainfrom
forehalo:refactor/cli

Conversation

@forehalo

@forehalo forehalo commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Summary

This refactor makes typed command arguments the source of truth for package-manager compatibility.

#[pm_args] reads field-level not_supported(...) metadata, including manager and version conditions

before:

#[derive(clap::Args)]
struct InstallArgs {
    #[arg(long)]
    fix_lockfile: bool,
}

// Simulated
match command {
  Command::Install(args) => {
    match manager {
      Yarn => {
        if args.fix_lockfile {
          output::warn("yarn@1 install does not support --fix-lockfile");
        }
        // ...
      },
      Npm => {
        if args.fix_lockfile {
          output::warn("npm install does not support --fix-lockfile");
        }
        // ...
      },
      Bun => {
        if args.fix_lockfile {
          output::warn("bun install does not support --fix-lockfile");
        }
        // ...
      }
    }
  },
  // ...
}

after:

#[pm_args]
#[derive(clap::Args)]
struct InstallArgs {
    #[arg(long, not_supported(npm, bun, yarn < "2"))]
    fix_lockfile: bool,
}

Given the detected package manager and its version, the generated diagnosis step automatically:

  • identifies active arguments that are unsupported;
  • resets only those arguments to their default value;
  • records a consistent warning before command resolution.

This removes repeated compatibility checks from every npm, pnpm, Yarn, and Bun resolver. Normal clap::Args and clap::Subcommand derives remain explicit. Hard errors, fallback commands, and manager-specific translations stay in the resolver.

Architecture and benefits

The production path is now:

typed clap arguments -> #[pm_args] diagnosis -> manager-specific Resolve<Args> -> Resolution -> runner

  • Global and local CLIs share one typed PackageManagerCommand surface.
  • Parsing, compatibility diagnosis, and production dispatch use the same argument types.
  • Resolution is side-effect free and directly testable. The runner executes the completed plan afterward.
  • Package-manager detection, downloads, caching, HTTP access, and shims now live in vite_pm_cli; the redundant vite_install crate is removed.

Adding a command

  1. Define an XxxArgs clap struct, or an XxxCommand nested subcommand enum, and add #[pm_args].
  2. Declare cross-manager and cross-version compatibility with field-level not_supported(...) rules.
  3. Implement Resolve<Args> for npm, pnpm, Yarn, and Bun. Build argv with CommandBuilder; share lowering helpers where command shapes match and branch only where manager behavior differs.
  4. Register the type in PackageManagerCommand or PmCommand, then select its project/manager policy.
  5. Test parsing and resolution with the shared test helpers. Add PTY snapshots for user-visible behavior.

Validation

  • just check
  • cargo test -p vite_pm_cli — 701 passed, 2 ignored
  • Affected-crate tests and strict Clippy with -D warnings
  • cargo fmt --all -- --check and git diff --check
  • Focused PTY snapshots for version, dedupe, install options, managed package-manager paths, shims, and CLI help

@netlify

netlify Bot commented Jul 10, 2026

Copy link
Copy Markdown

Deploy Preview for viteplus-preview canceled.

Name Link
🔨 Latest commit 5b4969e
🔍 Latest deploy log https://app.netlify.com/projects/viteplus-preview/deploys/6a50df20badbde00087b6bb4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant