Skip to content

fix: getting tangled stats from our backend#981

Open
fatfingers23 wants to merge 2 commits intonpmx-dev:mainfrom
fatfingers23:bug/tangled-stats
Open

fix: getting tangled stats from our backend#981
fatfingers23 wants to merge 2 commits intonpmx-dev:mainfrom
fatfingers23:bug/tangled-stats

Conversation

@fatfingers23
Copy link
Contributor

@fatfingers23 fatfingers23 commented Feb 5, 2026

Resolves: #844

The easiest way to get a at-uri for a tangled repo is from calling their webpage and parsing it out of the HTML. Moved this to the backend to resolve the current CORS errors.

I debated adding tangled.org to the cached fetch so that the HTML response can be cached, but that seems like a pretty big cached entry and I think in prod API endpoints are cached for a while.

Test repo: @weaver.sh/editor-collab

@vercel
Copy link

vercel bot commented Feb 5, 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 5, 2026 3:29am
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
docs.npmx.dev Ignored Ignored Preview Feb 5, 2026 3:29am
npmx-lunaria Ignored Ignored Feb 5, 2026 3:29am

Request Review

@codecov
Copy link

codecov bot commented Feb 5, 2026

Codecov Report

❌ Patch coverage is 0% with 1 line in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
app/composables/useRepoMeta.ts 0.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@fatfingers23 fatfingers23 marked this pull request as ready for review February 5, 2026 03:23
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 5, 2026

📝 Walkthrough

Walkthrough

The client-side composable useRepoMeta was simplified to call a new server API endpoint /api/atproto/tangled-stats/{owner}/{repo} instead of performing HTML scraping or Constellation-based lookups itself. A new server route server/api/atproto/tangled-stats/[owner]/[...repo].ts was added; it fetches the Tangled repo HTML, extracts an initial star count and at‑uri, and — if present — uses a Constellation instance to augment stars and forks. The endpoint returns { stars, forks }, defaulting to zeros on any error.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The pull request description clearly relates to the changeset, explaining the CORS issue with tangled.org and the decision to move parsing logic to the backend.
Linked Issues check ✅ Passed The PR successfully addresses issue #844 by moving tangled.org HTML parsing from client-side to backend via the new API endpoint, resolving CORS errors and restoring stars/forks functionality.
Out of Scope Changes check ✅ Passed All changes are directly scoped to resolving the tangled.org stats issue: new API endpoint for fetching stats and updated composable to use the endpoint instead of client-side parsing.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

🧹 Nitpick comments (1)
server/api/atproto/tangled-stats/[owner]/[...repo].ts (1)

49-51: Consider logging failed Constellation lookups for debugging.

Whilst silently failing is appropriate for user-facing behaviour, having no visibility into Constellation failures may make debugging production issues difficult.

💡 Optional: Add debug logging
-      } catch {
-        //failing silently since this is just an enhancement to the information already showing
+      } catch (e) {
+        // Failing silently since this is just an enhancement to the information already showing
+        console.debug('Constellation lookup failed for', atUri, e)
       }

@@ -0,0 +1,64 @@
import type { CachedFetchFunction } from '#shared/utils/fetch-cache-config'
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

Missing imports will cause compilation and runtime errors.

The file uses CachedFetchResult<T> (line 17) and Constellation (line 44) but neither is imported. This will cause TypeScript compilation errors and runtime failures.

🐛 Proposed fix to add missing imports
-import type { CachedFetchFunction } from '#shared/utils/fetch-cache-config'
+import type { CachedFetchFunction, CachedFetchResult } from '#shared/utils/fetch-cache-config'
+import { Constellation } from '#shared/utils/constellation'
📝 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
import type { CachedFetchFunction } from '#shared/utils/fetch-cache-config'
import type { CachedFetchFunction, CachedFetchResult } from '#shared/utils/fetch-cache-config'
import { Constellation } from '#shared/utils/constellation'

Comment on lines +4 to +5
let owner = getRouterParam(event, 'owner')
let repo = getRouterParam(event, 'repo')
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 | 🟠 Major

Validate owner and repo parameters before use.

getRouterParam can return undefined. Using undefined values directly in the URL (line 27) would result in https://tangled.org/undefined/undefined. Return an error response early if parameters are missing.

🛡️ Proposed fix to validate parameters
-  let owner = getRouterParam(event, 'owner')
-  let repo = getRouterParam(event, 'repo')
+  const owner = getRouterParam(event, 'owner')
+  const repo = getRouterParam(event, 'repo')
+
+  if (!owner || !repo) {
+    return { stars: 0, forks: 0 }
+  }

As per coding guidelines, ensure you write strictly type-safe code, for example by ensuring you always check when accessing values that may be 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
let owner = getRouterParam(event, 'owner')
let repo = getRouterParam(event, 'repo')
const owner = getRouterParam(event, 'owner')
const repo = getRouterParam(event, 'repo')
if (!owner || !repo) {
return { stars: 0, forks: 0 }
}

//Get counts of records that reference this repo in the atmosphere using constellation
const { data: allLinks } = await constellation.getAllLinks(atUri)
stars = allLinks.links['sh.tangled.feed.star']?.['.subject']?.distinct_dids ?? stars
forks = allLinks.links['sh.tangled.repo']?.['.source']?.distinct_dids ?? stars
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

Bug: forks fallback incorrectly uses stars instead of forks.

The nullish coalescing fallback for forks uses stars, which means if the Constellation lookup fails to find fork data, forks will incorrectly equal the star count.

🐛 Proposed fix for forks fallback
-        forks = allLinks.links['sh.tangled.repo']?.['.source']?.distinct_dids ?? stars
+        forks = allLinks.links['sh.tangled.repo']?.['.source']?.distinct_dids ?? forks
📝 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
forks = allLinks.links['sh.tangled.repo']?.['.source']?.distinct_dids ?? stars
forks = allLinks.links['sh.tangled.repo']?.['.source']?.distinct_dids ?? forks

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.

bug: tangled.org stars & fork count no longer load in

1 participant