Skip to content

feat: add deprecate command with custom reason#921

Open
eryue0220 wants to merge 29 commits intonpmx-dev:mainfrom
eryue0220:feat/resolve-40
Open

feat: add deprecate command with custom reason#921
eryue0220 wants to merge 29 commits intonpmx-dev:mainfrom
eryue0220:feat/resolve-40

Conversation

@eryue0220
Copy link
Copy Markdown
Contributor

resolve #40

@vercel
Copy link
Copy Markdown

vercel bot commented Feb 4, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
npmx.dev Ready Ready Preview, Comment Apr 17, 2026 8:51am
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
docs.npmx.dev Ignored Ignored Preview Apr 17, 2026 8:51am
npmx-lunaria Ignored Ignored Apr 17, 2026 8:51am

Request Review

@github-actions
Copy link
Copy Markdown

github-actions bot commented Feb 4, 2026

Lunaria Status Overview

🌕 This pull request will trigger status changes.

Learn more

By default, every PR changing files present in the Lunaria configuration's files property will be considered and trigger status changes accordingly.

You can change this by adding one of the keywords present in the ignoreKeywords property in your Lunaria configuration file in the PR's title (ignoring all files) or by including a tracker directive in the merged commit's description.

Tracked Files

File Note
i18n/locales/en.json Source changed, localizations will be marked as outdated.
i18n/locales/zh-CN.json Localization changed, will be marked as complete. 🔄️
Warnings reference
Icon Description
🔄️ The source for this localization has been updated since the creation of this pull request, make sure all changes in the source have been applied.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 4, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.
📝 Walkthrough

Walkthrough

This PR introduces package deprecation functionality allowing users to deprecate npm packages or specific versions with custom messages. It includes a new Vue 3 modal component for the deprecation workflow, CLI support via a new packageDeprecate() function, server-side operation handling for the package:deprecate operation type, schema validation for deprecation parameters, internationalization strings in English and Chinese, comprehensive component and a11y tests, and integration into the package detail page with ownership checks and version-aware UI.

Possibly related PRs

  • refactor: separate npm composables #827: Extracted and moved npm API utilities (fetchAllPackageVersions and related functions) to app/utils/npm/api that the deprecation modal component relies on for fetching version data.

Suggested reviewers

  • danielroe
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The pull request description 'resolve #40' directly references the linked issue and indicates the changeset addresses package deprecation functionality.
Linked Issues check ✅ Passed The pull request implements package deprecation with custom reason via the connector across frontend and CLI components, fulfilling the requirements in issue #40.
Out of Scope Changes check ✅ Passed All changes are scoped to package deprecation functionality: UI component, CLI operations, schemas, types, internationalisation, and tests. One minor addition to .gitignore for test coverage files appears incidental but acceptable.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov bot commented Feb 4, 2026

Codecov Report

❌ Patch coverage is 84.61538% with 14 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
app/pages/package/[[org]]/[name].vue 0.00% 7 Missing and 3 partials ⚠️
app/components/Package/DeprecatePackageModal.vue 95.00% 4 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
app/pages/package/[...package].vue (1)

1156-1169: Remove duplicate CSS classes.

The button has redundant inline-flex items-center (conflicting with flex) and w-full appearing twice in the class string.

🧹 Proposed fix
           <button
             type="button"
-            class="flex items-center justify-center w-full px-3 py-1.5 bg-bg-subtle rounded text-sm font-mono text-red-400 hover:text-red-500 transition-colors inline-flex items-center gap-1.5 w-full"
+            class="flex items-center justify-center gap-1.5 w-full px-3 py-1.5 bg-bg-subtle rounded text-sm font-mono text-red-400 hover:text-red-500 transition-colors"
             `@click`="deprecateModal?.open()"
           >

Comment thread app/components/Package/DeprecatePackageModal.vue Outdated
Comment thread app/components/Package/DeprecatePackageModal.vue Outdated
Comment thread app/components/Package/DeprecatePackageModal.vue
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
app/pages/package/[...package].vue (1)

1245-1256: Clean up duplicate CSS classes.

The button has redundant classes: both flex and inline-flex, and w-full appears twice.

♻️ Suggested fix
           <button
             type="button"
-            class="flex items-center justify-center w-full px-3 py-1.5 bg-bg-subtle rounded text-sm font-mono text-red-400 hover:text-red-500 transition-colors inline-flex items-center gap-1.5 w-full"
+            class="flex items-center justify-center gap-1.5 w-full px-3 py-1.5 bg-bg-subtle rounded text-sm font-mono text-red-400 hover:text-red-500 transition-colors"
             `@click`="deprecateModal?.open()"
           >

Comment thread cli/src/npm-client.ts
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
app/components/Package/DeprecatePackageModal.vue (2)

24-28: Use the imported t function instead of $t in the script block.

The component destructures t from useI18n() on line 12, but this computed uses $t. For consistency within the script setup, use the imported t function.

♻️ Proposed fix
 const modalTitle = computed(() =>
   deprecateVersion.value
-    ? `${$t('package.deprecation.modal.title')} ${props.packageName}@${deprecateVersion.value}`
-    : `${$t('package.deprecation.modal.title')} ${props.packageName}`,
+    ? `${t('package.deprecation.modal.title')} ${props.packageName}@${deprecateVersion.value}`
+    : `${t('package.deprecation.modal.title')} ${props.packageName}`,
 )

121-127: Consider removing inline focus-visible utilities from buttons.

Per project convention, focus-visible styling for buttons is applied globally via main.css with button:focus-visible { outline: 2px solid var(--accent); ... }. The inline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50 utilities override this global rule.

If this modal requires different focus styling, consider whether it should be consistent with the rest of the application or if an exception is warranted.

Based on learnings: "In the npmx.dev project, ensure that focus-visible styling for button and select elements is implemented globally in app/assets/main.css... Do not apply per-element inline utility classes."

Comment thread app/components/Package/DeprecatePackageModal.vue Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Comment thread cli/src/npm-client.ts Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
app/components/Package/DeprecatePackageModal.vue (2)

69-69: Consider adding optional chaining for defensive access.

If state.value.operations is ever undefined (e.g., during initialisation or after an error), this line would throw. Adding optional chaining aligns with the strict type-safety guideline.

🛡️ Proposed fix
-    const completedOp = state.value.operations.find(op => op.id === operation.id)
+    const completedOp = state.value.operations?.find(op => op.id === operation.id)

122-128: Remove inline focus-visible utilities on buttons to rely on global styling.

Both buttons in this component have custom focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50 classes. The project uses a global CSS rule for button focus-visible styling in main.css. Removing these inline utilities ensures consistency across the codebase.

This applies to the button on lines 164-175 as well.

♻️ Proposed fix
       <button
         type="button"
-        class="w-full px-4 py-2 font-mono text-sm text-fg-muted bg-bg-subtle border border-border rounded-md transition-colors duration-200 hover:text-fg hover:border-border-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50"
+        class="w-full px-4 py-2 font-mono text-sm text-fg-muted bg-bg-subtle border border-border rounded-md transition-colors duration-200 hover:text-fg hover:border-border-hover"
         `@click`="close"
       >

And for the deprecate button:

       <button
         type="button"
         :disabled="isDeprecating || !deprecateMessage.trim()"
-        class="w-full px-4 py-2 font-mono text-sm text-bg bg-fg rounded-md transition-colors duration-200 hover:bg-fg/90 disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50"
+        class="w-full px-4 py-2 font-mono text-sm text-bg bg-fg rounded-md transition-colors duration-200 hover:bg-fg/90 disabled:opacity-50 disabled:cursor-not-allowed"
         `@click`="handleDeprecate"
       >

Based on learnings: "In the npmx.dev project, focus-visible styling for buttons and selects is applied globally via main.css... individual buttons or selects in Vue components should not rely on inline focus-visible utility classes."

Comment thread app/components/Package/DeprecatePackageModal.vue
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
…feat/resolve-40

* 'feat/resolve-40' of github.com:eryue0220/npmx.dev:
  Update app/components/Package/DeprecatePackageModal.vue
@danielroe danielroe requested review from ghostdevv and removed request for ghostdevv February 26, 2026 12:07
@serhalp serhalp added the needs review This PR is waiting for a review from a maintainer label Mar 15, 2026
@serhalp serhalp added the stale This has become stale and may be closed soon label Apr 10, 2026
@MatteoGabriele
Copy link
Copy Markdown
Member

@eryue0220 Do you think these changes are still relevant and reviewable?
I think adding an easy way for maintainers to deprecate packages is quite useful, since deprecating packages on npm is not that straightforward.

@eryue0220
Copy link
Copy Markdown
Contributor Author

@eryue0220 Do you think these changes are still relevant and reviewable? I think adding an easy way for maintainers to deprecate packages is quite useful, since deprecating packages on npm is not that straightforward.

Okay, and I've resolved the conflicts.

Copy link
Copy Markdown
Member

@MatteoGabriele MatteoGabriele left a comment

Choose a reason for hiding this comment

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

I've given a quick check of the UI, and besides the button changes I mentioned, it looks good!
That said, when I try to deprecate (I actually have a package I can deprecate), it doesn't work and returns a 400 Bad Request.

Comment on lines +1019 to +1032
<!-- Deprecation (when connected as package owner; hidden when current version is already deprecated) -->
<div
v-if="isConnected && resolvedVersion && isPackageOwner && !isCurrentVersionDeprecated"
class="space-y-1"
>
<button
type="button"
class="flex items-center justify-center gap-1.5 w-full px-3 py-1.5 bg-bg-subtle rounded text-sm font-mono text-red-400 hover:text-red-500 transition-colors"
@click="deprecateModal?.open()"
>
<span class="i-carbon-warning-alt w-4 h-4 shrink-0" aria-hidden="true" />
{{ $t('package.deprecation.action') }}
</button>
</div>
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.

I think the button needs to be visually aligned with the rest of the sidebar elements, and we should use ButtonBase with the Lucide icons as well.
I was playing around with it, so if you want to can just use this suggestion. Let me know what you think.

Suggested change
<!-- Deprecation (when connected as package owner; hidden when current version is already deprecated) -->
<div
v-if="isConnected && resolvedVersion && isPackageOwner && !isCurrentVersionDeprecated"
class="space-y-1"
>
<button
type="button"
class="flex items-center justify-center gap-1.5 w-full px-3 py-1.5 bg-bg-subtle rounded text-sm font-mono text-red-400 hover:text-red-500 transition-colors"
@click="deprecateModal?.open()"
>
<span class="i-carbon-warning-alt w-4 h-4 shrink-0" aria-hidden="true" />
{{ $t('package.deprecation.action') }}
</button>
</div>
<!-- Deprecation (when connected as package owner; hidden when current version is already deprecated) -->
<div
v-if="isConnected && resolvedVersion && isPackageOwner && !isCurrentVersionDeprecated"
class="pl-7"
>
<ButtonBase
type="button"
variant="secondary"
class="w-full text-red"
@click="deprecateModal?.open()"
classicon="i-lucide:triangle-alert text-red"
>
{{ $t('package.deprecation.action') }}
</ButtonBase>
</div>

v-if="pkg"
ref="deprecateModal"
:package-name="pkg.name"
:version="resolvedVersion ?? ''"
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.

What happens if we don't get the version?

@MatteoGabriele
Copy link
Copy Markdown
Member

@43081j Since we talked about this on Bluesky, what do you think? UI-wise, it works for me. I also think the button's placement is visible enough without being too prominent.

Screenshot 2026-04-18 at 13 59 01

@github-actions github-actions bot removed the stale This has become stale and may be closed soon label Apr 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs review This PR is waiting for a review from a maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

add package deprecation with custom reason

5 participants