fix(migrate): remove scoped Prettier plugins and shareable configs - #2557
fix(migrate): remove scoped Prettier plugins and shareable configs#2557m0g3r wants to merge 1 commit into
Conversation
`rewritePrettierPackageJson` matched only the exact name `prettier` and the flat `prettier-plugin-*` prefix, so a migrated project kept installing dead Prettier packages under any other naming shape — scoped plugins such as `@trivago/prettier-plugin-sort-imports`, `@ianvs/prettier-plugin-sort-imports` and `@shopify/prettier-plugin-liquid`, everything in the official `@prettier/` scope (`plugin-php`, `plugin-xml`, `plugin-ruby`), shareable configs, and `@types/prettier`. The asymmetry was arbitrary rather than deliberate: the sibling ESLint path already recognises all of these shapes via `isEslintEcosystemDep`, including the scoped `^@[^/]+\/eslint-(plugin|config|formatter)(-.+)?$` form. Add `isPrettierEcosystemDep` mirroring that helper, and route both dependency loops through it. The matched set stays deliberately narrow: names that merely contain "prettier" (`eslint-config-prettier`, `prettierx`, an unrelated `@prettierx/` scope) are preserved. The dependency fields scanned are unchanged — `peerDependencies` and `optionalDependencies` are still left alone. `rewritePrettierPackageJson` becomes exported, per `migrator/README.md`'s rule that module functions are exported so the barrel surfaces them, which also lets it be unit-tested like its ESLint counterpart.
✅ Deploy Preview for viteplus-preview ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 539ec1aa2f
ℹ️ 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".
| // Scopes whose every package is part of the Prettier ecosystem. | ||
| // @prettier/* — official Prettier scope (@prettier/plugin-php, | ||
| // @prettier/plugin-xml, @prettier/plugin-ruby, @prettier/sync) | ||
| const PRETTIER_ECOSYSTEM_SCOPES = ['@prettier/']; |
There was a problem hiding this comment.
Preserve non-plugin packages in the @prettier scope
When a project imports @prettier/sync programmatically and its Prettier peer remains available transitively or through automatic peer installation, matching the entire @prettier/ scope now deletes the package even though this migration only converts configuration and CLI scripts—it does not rewrite source imports. The subsequent install therefore makes that import fail. Restrict scope-wide cleanup to actual plugin packages, or check source usage before deleting non-plugin APIs such as @prettier/sync.
Useful? React with 👍 / 👎.
| // Flat name prefixes that mark a Prettier-only package. | ||
| const PRETTIER_ECOSYSTEM_PREFIXES = ['prettier-plugin-', 'prettier-config-']; |
There was a problem hiding this comment.
Update the migration contract for the expanded cleanup
This expands destructive manifest rewriting to prettier-config-*, scoped plugin/config packages, and the entire @prettier/* scope, but the documented migration contract was not updated: rfcs/migration-command.md step 4 still promises removal only of prettier and unscoped prettier-plugin-*, while the canonical docs/guide/migrate-rules.md does not describe these additional removals. Update the migration documentation so users reviewing generated manifest changes can predict the new cleanup.
AGENTS.md reference: AGENTS.md:L66-L67
Useful? React with 👍 / 👎.
Problem
vp migrateremoves Prettier itself, but a migrated project keeps installing dead Prettierpackages under most naming shapes.
rewritePrettierPackageJsonmatched only the exact nameprettierand the flatprettier-plugin-*prefix, so all of these survived migration:@trivago/prettier-plugin-sort-imports,@ianvs/prettier-plugin-sort-imports,@shopify/prettier-plugin-liquid@prettier/scope —@prettier/plugin-php,@prettier/plugin-xml,@prettier/plugin-rubyprettier-config-*,@scope/prettier-config@types/prettierThe asymmetry looks arbitrary rather than intentional: unscoped
prettier-plugin-sort-importsisremoved, while the scoped package of the same name is not.
The sibling ESLint path already gets this right.
isEslintEcosystemDepinmigrator/eslint.tsrecognises named packages, flat prefixes, whole scopes, the scoped^@[^/]+\/eslint-(plugin|config|formatter)(-.+)?$form, and treats@types/NAMEsymmetricallywith
NAME.Changes
Adds
isPrettierEcosystemDepmirroringisEslintEcosystemDep, and routes both dependency loopsthrough it.
The matched set is deliberately narrow, and a test pins that:
eslint-config-prettier,eslint-plugin-prettier,prettierx, and an unrelated@prettierx/scope are all preserved.Also deliberately unchanged:
peerDependenciesandoptionalDependenciesare still left alone. TheESLint path does scrub them, but whether migration should silently drop a declared peer
dependency is exactly what a P1 on feat(migrate): preserve dynamic Oxlint and Oxfmt configs #2483 is currently about, so I have not imported that decision
here.
leaves
"devDependencies": {}. Same reasoning — separate concern, separate PR if wanted.rewritePrettierPackageJsonbecomes exported.migrator/README.mdrule 1 asks for module functionsto be exported so the barrel surfaces them, and it makes the function unit-testable exactly like
rewriteEslintPackageJson.Testing
Six cases added to
migrator.spec.ts, next to therewriteEslintPackageJsonblock and followingits conventions.
Verified in both directions: with the old matcher restored and the new tests kept, 4 fail;
with the fix, 6/6 pass. The two that pass either way are the guards for behaviour that is meant
to be unchanged (unrelated-name preservation, and the no-op case).
Checks actually run:
migrator.spec.ts— before/after diffed in the same build state: identical failure set bothways (139), with the change adding exactly 6 passing tests (206 → 212).
oxlint@1.79.0(the repo's pin) with-D correctness -D perf -D suspiciouson both changedfiles — no new findings. The one reported error is pre-existing and byte-identical on the
unmodified files, and is a rule this repo sets to
offinvite.config.ts.oxfmt@0.64.0(the repo's pin), configured from this repo'sfmtblock — clean, and clean onuntouched control files too.
git diff --check— clean.Not run:
vp check,pnpm test:unit,tsgo, and the PTY snapshot suite, which need a fullworkspace build my environment cannot produce. No PTY fixture covers
rewritePrettierPackageJson,and this change adds no CLI output.
AI assistance
Claude Opus 5 wrote the implementation, the tests, and this description. The change is
agent-authored and has not had a separate human review. Every result quoted above is from an actual
run, not an estimate.