Skip to content

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

Merged
fengmk2 merged 1 commit into
voidzero-dev:mainfrom
forehalo:refactor/cli
Aug 3, 2026
Merged

refactor(pm-cli): consolidate package manager infrastructure#2140
fengmk2 merged 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 b3a8b10
🔍 Latest deploy log https://app.netlify.com/projects/viteplus-preview/deploys/6a7040414064760008fd4a30

@liangmiQwQ

Copy link
Copy Markdown
Collaborator

Perhaps it is a nice solution for #1914 💛

@forehalo
forehalo force-pushed the refactor/cli branch 2 times, most recently from b349ce0 to 9ceaa2c Compare August 3, 2026 06:09
@forehalo
forehalo marked this pull request as ready for review August 3, 2026 06:14
@fengmk2

fengmk2 commented Aug 3, 2026

Copy link
Copy Markdown
Member

@codex review

@fengmk2 fengmk2 added test: e2e Auto run e2e tests test: install-e2e run vite install e2e test test: create-e2e Run `vp create` e2e tests test: sfw labels Aug 3, 2026
@fengmk2 fengmk2 self-assigned this Aug 3, 2026
@fengmk2
fengmk2 self-requested a review August 3, 2026 06:34
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Chef's kiss.

Reviewed commit: 9ceaa2c891

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@fengmk2 fengmk2 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@forehalo BIG thanks! LGTM

@fengmk2
fengmk2 merged commit c1574dd into voidzero-dev:main Aug 3, 2026
155 of 156 checks passed
fengmk2 added a commit that referenced this pull request Aug 3, 2026
## Summary

Re-does #2301 on top of the pm-cli consolidation (#2140), which moved
`vite_install/src/package_manager.rs` into `crates/vite_pm_cli` and made
the old branch unrebaseable.

- The `packageManager` hash names the main `bun` npm package, so the
platform tarball (`@oven/bun-{os}-{arch}`) was downloaded without any
verification.
- Extracts the registry `dist.integrity` lookup that the pnpm >= 12
native path already implements inline into a shared
`fetch_platform_integrity` helper, and applies it to the bun platform
tarball as well.
- The pnpm >= 12 path now uses the same helper, so its behavior is
unchanged.

Supersedes #2301.

Co-authored-by: MK (fengmk2) <fengmk2@gmail.com>
fengmk2 added a commit that referenced this pull request Aug 3, 2026
## Summary

Adds `vp pm patch` and `vp pm patch-commit` commands, resolved per
package manager through the `resolution/commands` layer.

| Package manager | `vp pm patch <pkg>` | `vp pm patch-commit <dir>` |
| --- | --- | --- |
| pnpm | `pnpm patch <pkg>` | `pnpm patch-commit <dir>` |
| bun | `bun patch <pkg>` | `bun patch --commit <dir>` |
| Yarn Berry | `yarn patch <pkg>` | `yarn patch-commit <dir>` |
| npm / Yarn Classic | warns and exits successfully
(`UnsupportedCommandNoop`) | same |

Both commands forward `-- <args>` pass-through arguments and require a
project (`RequireProject` manager policy).

Supersedes #2144, reimplemented on top of the package manager
infrastructure consolidation in #2140.

---------

Co-authored-by: MK (fengmk2) <fengmk2@gmail.com>
fengmk2 added a commit that referenced this pull request Aug 5, 2026
…t variable renames, and install fixes (#2325)

Release vite-plus v0.2.8: monorepo target resolution, breaking `VP_*`
environment variable renames, and install fixes.

Bare `vp dev`/`build`/`preview`/`pack` at a monorepo root now resolve a
target package instead of silently running against the root, and three
Vite+-specific environment variables move to the `VP_*` prefix without
compatibility aliases. Two failures that broke Vite+ before it could run
are also fixed: the crash on container images that ship no CA
certificates, and the missing Rolldown binding under pnpm's global
virtual store.

### Breaking Changes

- Rename three Vite+-specific environment variables to the `VP_*`
prefix, with no compatibility aliases, so the old names stop working
([#2312](#2312)), by
@jong-kyung:

  | Old | New |
  | --- | --- |
  | `VITE_LOG` | `VP_LOG` |
  | `VITE_GLOBAL_CLI_JS_SCRIPTS_DIR` | `VP_GLOBAL_CLI_JS_SCRIPTS_DIR` |
  | `VITE_UPDATE_TASK_TYPES` | `VP_UPDATE_TASK_TYPES` |

Update any shell profile, CI job, or Dockerfile that sets the old names.

### Highlights

- Resolve a target package for `vp dev`, `build`, `preview`, and `pack`
at a monorepo root: interactive shells get a fuzzy package picker,
non-interactive runs list the candidates and exit 1 instead of building
the root, and a new global `-C <dir>` flag or a `defaultPackage` setting
(a single directory, or an object mapping each of the four commands to
its own directory) skips the prompt
([#2031](#2031),
[#2305](#2305)), by
@fengmk2
- Stop aborting with exit 134 on container images that ship no CA
certificates (Debian slim, distroless): the shared HTTP client now
retries once with the bundled Mozilla root list, like Node's own bundled
roots, and reports a real error instead of panicking when it still
cannot be built
([#2273](#2273),
[#2295](#2295)), by
@jbmusso and @fengmk2
- Resolve the bundled Rolldown binding through platform packages instead
of an undeclared require back into `vite-plus`, fixing `Cannot find
module 'vite-plus/binding'` under pnpm `enable-global-virtual-store` and
in standalone `@voidzero-dev/vite-plus-core` installs
([#2313](#2313)), by
@fengmk2
- Add `vp pm ci` for reproducible frozen-lockfile installs, and `vp pm
patch` / `vp pm patch-commit` for editing dependencies in place on pnpm,
bun, and Yarn Berry (npm and Yarn Classic warn and exit successfully)
([#2082](#2082),
[#2308](#2308)), by
@forehalo and @jong-kyung

### Features

- Upgrade the bundled toolchain: vite `8.1.5` -> `8.2.0`, rolldown
`1.2.0` -> `1.2.2`, oxlint `1.75.0` -> `1.76.0`, oxfmt `0.60.0` ->
`0.61.0`, and Vite DevTools `0.4.5` -> `0.4.10`
([#2302](#2302),
[#2311](#2311)), by
@voidzero-guard[bot]. The new oxfmt and oxlint can flag code that passed
before, so run `vp fmt` after upgrading if your CI runs `vp check`.
- Read the Node.js version from `.nvmrc` when no other version source is
present ([#2244](#2244)),
by @BlankParticle
- Support pnpm v12, which ships as a native binary: Vite+ now downloads
the platform-specific `@pnpm/exe.*` package and generates native shims,
so `pnpm` and `pnpx` work instead of failing to exec
([#2289](#2289)), by
@jong-kyung
- Verify the downloaded bun platform tarball against the registry
`dist.integrity` hash
([#2310](#2310)), by
@jong-kyung

### Fixes & Enhancements

- Let `vp config` install the Git hook dispatcher without creating or
modifying project hook scripts or staged-file configuration, so a custom
`.vite-hooks/pre-commit` survives
([#2280](#2280)), by
@TheAlexLichter
- Nest immutable global package installs under
`packages/<package>/<uuid>` instead of using `#` in the path, which Node
treated as a URL fragment and which broke dynamic imports inside
installed packages
([#2222](#2222)), by
@liangmiQwQ
- Keep the recorded version spec on global installs, so `vp update -g`
follows a dist tag or range instead of silently resolving back to
`latest`, `vp outdated -g` reports Wanted versus Latest, and `vp update
-g --latest` explicitly moves packages back to `latest`
([#2249](#2249)), by
@TheAlexLichter
- Stop deleting a managed Node.js runtime that another process is
concurrently installing
([#2248](#2248)), by
@shulaoda
- Preserve the real exit code when a spawned process is terminated by a
signal on Unix
([#2154](#2154)), by
@liangmiQwQ
- Honor an explicit `vp create --package-manager` outside monorepos
instead of inheriting the manager from a non-monorepo ancestor directory
([#2226](#2226)), by
@jong-kyung
- Scaffold the `vite:library` template into a directory that contains
only `.git`, while still refusing to overwrite existing user files
([#2287](#2287)), by
@RSS1102
- Render help for delegated commands from the local CLI, so `vp
<command> --help` matches the installed toolchain instead of drifting
([#2184](#2184)), by
@liangmiQwQ
- Resolve `typeAware` and `typeCheck` options inherited through Oxlint
`extends`, so `vp check --no-lint` runs and classifies type checking
correctly
([#2228](#2228)), by
@jong-kyung
- Report `(no version)` instead of `unknown` when globally installing a
local package that has no `version` field
([#2232](#2232)), by
@liangmiQwQ

### Refactor

- Rename the Git hooks environment variable to `VP_GIT_HOOKS`, keeping
`VITE_GIT_HOOKS` working as a deprecated alias
([#2195](#2195)), by
@dennybiasiolli
- Consolidate the package manager infrastructure so typed command
arguments are the source of truth for per-manager compatibility
([#2140](#2140)), by
@forehalo
- Generate the Zed language settings from a language list instead of 17
near-identical blocks
([#2294](#2294)), by
@jong-kyung
- Share the agent-file detect and write traversal helpers so both passes
apply identical rules
([#2296](#2296)), by
@jong-kyung
- Drop redundant clippy allow attributes in the global CLI
([#2235](#2235)), by
@shulaoda

### Docs

- Avoid a duplicate `vp` installation step in the onboarding prompt
([#2291](#2291)), by
@Arcadi4
- Recommend stacked pull requests for submitting changes
([#2281](#2281)), by
@fengmk2
- Correct stale delegation comments in the global CLI
([#2236](#2236)), by
@shulaoda
- Improve the release draft review guidance in the release-manager skill
([#2285](#2285)), by
@wan9chi

### Chore

- Stop emitting unmet peer warnings for the `vite-plus` peer of oxfmt
and oxlint on every install
([#2321](#2321)), by
@fengmk2
- Remove duplicate direct dependency declarations so each build
dependency is owned by one workspace
([#2318](#2318)), by
@jong-kyung
- Declare `@emnapi` peers where `@napi-rs/cli` is used
([#2319](#2319)), by
@jong-kyung
- Exclude `rollup-tests` from the workspace and update `basic-ftp`
([#2322](#2322)), by
@fengmk2
- Remove unused `EnvConfig` fields
([#2320](#2320)), by
@jong-kyung
- Remove the obsolete peer dependency merger tool
([#2303](#2303)), by
@jong-kyung
- Stop the staging deploy from triggering on external pull requests
([#2293](#2293)), by
@BlankParticle
- Kill the real `vp` process, and kill it before its children, in the
`env_install_interrupt` snapshot test
([#2299](#2299),
[#2316](#2316)), by
@fengmk2
- Suppress racy optimizer logs in the `vitest_browser_mode` snapshot
test ([#2297](#2297)), by
@fengmk2
- Remove the obsolete auto-install environment from the snapshot tests
([#2163](#2163)), by
@liangmiQwQ

### Bundled Versions

| Tool | Version | Source |
| --------------- | ---------- |
-------------------------------------------------------------------------------------------------
|
| vite | `8.2.0` |
[`fa79f9a`](vitejs/vite@fa79f9a)
|
| rolldown | `1.2.2` |
[`872b98a`](rolldown/rolldown@872b98a)
|
| tsdown | `0.22.14` | [npm](https://npmx.dev/package/tsdown/v/0.22.14)
|
| vitest | `4.1.10` | [npm](https://npmx.dev/package/vitest/v/4.1.10) |
| oxlint | `1.76.0` | [npm](https://npmx.dev/package/oxlint/v/1.76.0) |
| oxlint-tsgolint | `7.0.2001` |
[npm](https://npmx.dev/package/oxlint-tsgolint/v/7.0.2001) |
| oxfmt | `0.61.0` | [npm](https://npmx.dev/package/oxfmt/v/0.61.0) |

### Upgrade

```bash
vp upgrade
```

### New Contributors

@jbmusso, @Arcadi4, @dennybiasiolli, @RSS1102

**Full Changelog**:
v0.2.7...v0.2.8

---

Merging this PR will trigger the release workflow.

---------

Co-authored-by: voidzero-guard[bot] <278573678+voidzero-guard[bot]@users.noreply.github.com>
Co-authored-by: MK <fengmk2@gmail.com>
@forehalo
forehalo deleted the refactor/cli branch August 5, 2026 07:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test: create-e2e Run `vp create` e2e tests test: e2e Auto run e2e tests test: install-e2e run vite install e2e test test: sfw

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants