Skip to content

Conversation

@Tobbe
Copy link

@Tobbe Tobbe commented Feb 12, 2026

I started working on this new graph. WDYT?
I wanted to be able to see how "healthy", from a number-of-contibutors perspective a package is.
Like, even if a package has hundreds of contributors, maybe those are all from years past, and the package is now basically only kept alive by one person, which isn't too good from a reliability/bus factor point of view
It uses the GitHub API, so only works for packages that have a github repo linked in the package metadata

image

@vercel
Copy link

vercel bot commented Feb 12, 2026

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

Project Deployment Actions Updated (UTC)
npmx.dev Ready Ready Preview, Comment Feb 13, 2026 0:21am
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
docs.npmx.dev Ignored Ignored Preview Feb 13, 2026 0:21am
npmx-lunaria Ignored Ignored Feb 13, 2026 0:21am

Request Review

@github-actions
Copy link

github-actions bot commented Feb 12, 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
lunaria/files/en-GB.json Localization changed, will be marked as complete. 🔄️
lunaria/files/en-US.json Source changed, localizations will be marked as outdated.
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.

@codecov
Copy link

codecov bot commented Feb 12, 2026

Codecov Report

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

Files with missing lines Patch % Lines
app/composables/useCharts.ts 4.09% 90 Missing and 27 partials ⚠️
app/components/Package/TrendsChart.vue 56.47% 26 Missing and 11 partials ⚠️
app/pages/package/[[org]]/[name].vue 0.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 12, 2026

📝 Walkthrough

Walkthrough

This PR adds per-package repository references and a new "contributors" metric to the trends chart. It introduces a repoRef prop, repoRefsByPackage state, and loadRepoRefsForPackages to fetch repo refs from package-meta. The Metric system now uses MetricContext (packageName, repoRef) and includes a contributors metric when a GitHub repo is available. Multi-package flows and granularity handling were updated to use per-package repo refs. Server and fixture support for GitHub contributors stats and a new contributors-evolution API were added, alongside client-side contributor evolution fetching and caching and localization entries for "Contributors".

Possibly related PRs

Suggested reviewers

  • danielroe
  • graphieros
🚥 Pre-merge checks | ✅ 1 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Merge Conflict Detection ⚠️ Warning ❌ Merge conflicts detected (41 files):

⚔️ .gitignore (content)
⚔️ CONTRIBUTING.md (content)
⚔️ app/components/AppHeader.vue (content)
⚔️ app/components/Compare/FacetSelector.vue (content)
⚔️ app/components/Header/SearchBox.vue (content)
⚔️ app/components/Package/Card.vue (content)
⚔️ app/components/Package/Keywords.vue (content)
⚔️ app/components/Package/Maintainers.vue (content)
⚔️ app/components/Package/ManagerSelect.vue (content)
⚔️ app/components/Package/TrendsChart.vue (content)
⚔️ app/components/Package/VersionDistribution.vue (content)
⚔️ app/components/Package/Versions.vue (content)
⚔️ app/components/Package/WeeklyDownloadStats.vue (content)
⚔️ app/components/Readme.vue (content)
⚔️ app/composables/useCharts.ts (content)
⚔️ app/composables/useMarkdown.ts (content)
⚔️ app/composables/useStructuredFilters.ts (content)
⚔️ app/pages/index.vue (content)
⚔️ app/pages/package/[[org]]/[name].vue (content)
⚔️ app/pages/search.vue (content)
⚔️ app/utils/frameworks.ts (content)
⚔️ app/utils/prehydrate.ts (content)
⚔️ i18n/locales/en.json (content)
⚔️ i18n/locales/es.json (content)
⚔️ i18n/locales/pl-PL.json (content)
⚔️ i18n/locales/zh-CN.json (content)
⚔️ i18n/schema.json (content)
⚔️ lunaria/files/en-GB.json (content)
⚔️ lunaria/files/en-US.json (content)
⚔️ lunaria/files/es-419.json (content)
⚔️ lunaria/files/es-ES.json (content)
⚔️ lunaria/files/pl-PL.json (content)
⚔️ lunaria/files/zh-CN.json (content)
⚔️ modules/runtime/server/cache.ts (content)
⚔️ nuxt.config.ts (content)
⚔️ package.json (content)
⚔️ server/middleware/canonical-redirects.global.ts (content)
⚔️ shared/utils/package-analysis.ts (content)
⚔️ test/nuxt/a11y.spec.ts (content)
⚔️ test/nuxt/composables/use-markdown.spec.ts (content)
⚔️ vercel.json (content)

These conflicts must be resolved before merging into main.
Resolve conflicts locally and push changes to this branch.
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The pull request description is directly related to the changeset, detailing the addition of a new GitHub contributors graph feature to visualise package health based on contributor activity trends.

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

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
⚔️ Resolve merge conflicts (beta)
  • Auto-commit resolved conflicts to branch tobbe-feat-gh-contrib-graph
  • Post resolved changes as copyable diffs in a comment

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
app/components/Package/TrendsChart.vue (1)

764-766: Consider defensive check for array access.

Accessing METRICS.value[0] without a guard could technically return undefined if the array were empty. While METRICS always contains at least two metrics in practice, adding a defensive check aligns with strict type-safety guidelines.

🛡️ Optional defensive improvement
 const activeMetricDef = computed(
-  () => METRICS.value.find(m => m.id === selectedMetric.value) ?? METRICS.value[0],
+  () => METRICS.value.find(m => m.id === selectedMetric.value) ?? METRICS.value[0] ?? METRICS.value.find(() => true),
 )

Alternatively, ensure the type signature accounts for this:

 const activeMetricDef = computed(
-  () => METRICS.value.find(m => m.id === selectedMetric.value) ?? METRICS.value[0],
+  () => {
+    const found = METRICS.value.find(m => m.id === selectedMetric.value)
+    if (found) return found
+    const first = METRICS.value[0]
+    if (first) return first
+    throw new Error('No metrics available')
+  },
 )

As per coding guidelines: "ensure you always check when accessing an array value by index".


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

Copy link
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

Copy link
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 on lines +1368 to +1372
<PackageWeeklyDownloadStats
:packageName
:createdIso="pkg?.time?.created ?? null"
:repoRef="repoRef"
/>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Fix repoRef nullability for PackageWeeklyDownloadStats.

repoRef can be null from useRepoMeta, but the child prop expects RepoRef | undefined, causing the reported type check failure. Normalise null to undefined (or widen the prop type).

🛠️ Suggested fix
-            :repoRef="repoRef"
+            :repoRef="repoRef ?? undefined"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<PackageWeeklyDownloadStats
:packageName
:createdIso="pkg?.time?.created ?? null"
:repoRef="repoRef"
/>
<PackageWeeklyDownloadStats
:packageName
:createdIso="pkg?.time?.created ?? null"
:repoRef="repoRef ?? undefined"
/>
🧰 Tools
🪛 GitHub Check: 💪 Type check

[failure] 1371-1371:
Type 'RepoRef | null' is not assignable to type 'RepoRef | undefined'.

@Tobbe Tobbe changed the title feat: Add GitHub contributors graph feat: add GitHub contributors graph Feb 12, 2026
@graphieros
Copy link
Contributor

graphieros commented Feb 12, 2026

When switching to monthly or yearly, the component is designed to display estimations for incomplete periods.
It was designed originally to chart downloads. However this KPI is not compatible with estimations. The component must be adapted to show estimations for compatible facets.

The facet does not appear to be working on the compare page.

I would also move the fetching to the useCharts composable

@graphieros graphieros requested a review from serhalp February 12, 2026 21:51
@Tobbe
Copy link
Author

Tobbe commented Feb 12, 2026

When switching to monthly or yearly, the component is designed to display estimations for incomplete periods. It was designed originally to chart downloads. However this KPI is not compatible with estimations. The component must be adapted to show estimations for compatible facets.

Yes, I did find it a bit weird that it was estimating how many contributors a package will have 😀 How should we handle the incomplete period though? 🤔

@graphieros
Copy link
Contributor

When switching to monthly or yearly, the component is designed to display estimations for incomplete periods. It was designed originally to chart downloads. However this KPI is not compatible with estimations. The component must be adapted to show estimations for compatible facets.

Yes, I did find it a bit weird that it was estimating how many contributors a package will have 😀 How should we handle the incomplete period though? 🤔

We are dealing with absolutes. n contributors today does not add up with n yesterday. So weekly, monthly, yearly should be averages.

@graphieros graphieros marked this pull request as draft February 12, 2026 22:07
@Tobbe
Copy link
Author

Tobbe commented Feb 12, 2026

The facet does not appear to be working on the compare page.

Yeah, I hadn't gotten around to fully testing that one yet.
I've made it work now (locally)
image

But I also need to find a package that doesn't have a GitHub repo in its package.json to test with.
You don't happen to know of one offhand, do you?

@Tobbe
Copy link
Author

Tobbe commented Feb 12, 2026

I faked one not having a github link, just to be able to test how it'd work.
It now prints a small notice for packages not included

image

@Tobbe
Copy link
Author

Tobbe commented Feb 12, 2026

When switching to monthly or yearly, the component is designed to display estimations for incomplete periods. It was designed originally to chart downloads. However this KPI is not compatible with estimations. The component must be adapted to show estimations for compatible facets.

Yes, I did find it a bit weird that it was estimating how many contributors a package will have 😀 How should we handle the incomplete period though? 🤔

We are dealing with absolutes. n contributors today does not add up with n yesterday. So weekly, monthly, yearly should be averages.

Likes also isn't additive, right? So maybe likes and contributors should be handled differently compared to downloads.
But I don't want to touch the logic for existing graphs in this PR. So how about we leave it like it is for all three facets for now, and then have another PR to fix this logic?

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.

2 participants