deno
dbcd1a91 - feat(cli): auto-migrate pnpm-workspace.yaml on resolution failure (#34993)

Commit
27 days ago
feat(cli): auto-migrate pnpm-workspace.yaml on resolution failure (#34993) Deno deliberately does not read `pnpm-workspace.yaml` during module resolution. A project whose workspace members (or catalog versions) live in that file therefore fails to resolve, and the baked-in error ("did you forget to run `deno install`?") sends the user in circles. Instead of adding a dedicated subcommand for a single package manager, this handles pnpm automatically on the failure path. When a command exits with a workspace/npm resolution error and a `pnpm-workspace.yaml` is found in the cwd or an ancestor, Deno converts its `packages`, `catalog`, and `catalogs` into the equivalent config fields and prints a note telling the user to run the command again: ``` error: Could not find package.json with name '@scope/lib' in workspace. warning: Found pnpm-workspace.yaml nearby, which Deno does not read directly. hint: Migrated its workspace configuration into package.json. Run the command again. ``` The second run resolves normally. npm, Yarn, and Bun workspaces already work out of the box because they store their globs in `package.json#workspaces`; pnpm is the only major package manager that uses a separate file, which is why it is the lone case that needs this bridge. The migration prefers `package.json`. A pnpm project already keeps its config there, and Deno reads `workspaces`, `catalog`, and `catalogs` from it natively (top-level `catalog`/`catalogs` even take precedence), so the project's config stays in one file. It falls back to `deno.json`/`deno.jsonc` only when there is no `package.json` next to the `pnpm-workspace.yaml`. The conversion preserves existing comments and formatting via the jsonc CST and never overwrites fields the user already set, so re-running is a no-op once the configuration is in place (no migration loop). Keys with no equivalent in Deno (`overrides`, `patchedDependencies`, `registries`, ...) are listed in a note rather than silently dropped. YAML parsing reuses the in-tree `yaml_parser` crate that `deno fmt` already uses, so no new dependency family is added. Implementation lives in `cli/util/pnpm_workspace.rs` and is invoked from `exit_for_error`, the single chokepoint every subcommand's errors pass through (it formats both Rust errors and downcast JS errors), so the detection is entirely off the resolution hot path. This run-it-again flow replaces the earlier `deno migrate pnpm` subcommand and its separate resolution-failure hint. Closes #29786.
Author
Parents
Loading