Skip to content

Comments

feat: add github connection#1613

Draft
olivermrose wants to merge 8 commits intonpmx-dev:mainfrom
olivermrose:feat/gh-connection
Draft

feat: add github connection#1613
olivermrose wants to merge 8 commits intonpmx-dev:mainfrom
olivermrose:feat/gh-connection

Conversation

@olivermrose
Copy link
Contributor

@olivermrose olivermrose commented Feb 23, 2026

🔗 Linked issue

#479

🧭 Context

Implements GitHub OAuth, displays whether a repo is starred or not, and the ability to star/unstar through the UI. This does not implement the #32 portion.

Demo
demo.mp4

📚 Description

.env requires GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET from an OAuth app in order to run. The redirect uri needs to be http://127.0.0.1:3000, not http://localhost:3000. This also needs to be the url that is visited in the browser in order for the cookie to persist properly.

I renamed/moved some of the AT Protocol files to distinguish between the auth providers since there's more than one now. I based the GH auth off the existing AT route, and I didn't run into any issues, but it's been a while since I've manually handled oauth flows, so there's a chance I've missed an edge case or something.

For the starring API routes, I just left them all under /github because I wasn't sure if a /star path was needed/wanted.

@vercel
Copy link

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

Request Review

@github-actions
Copy link

github-actions bot commented Feb 23, 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.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 23, 2026

📝 Walkthrough

Walkthrough

Adds GitHub OAuth and starring support alongside existing Atproto auth: new GitHub composable and GitHub modal UI, AccountMenu updates to show GitHub connection and stacked avatars, server API routes for GitHub OAuth and star management, new shared schema and session github field, Atproto endpoints moved under /api/auth/atproto/, adjustments to useAtproto and modal identifiers, and localisation entries for GitHub-related UI.

Possibly related PRs

Suggested reviewers

  • danielroe
🚥 Pre-merge checks | ✅ 1
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The pull request description clearly relates to the changeset, detailing GitHub OAuth implementation, starring functionality, and file reorganization.

✏️ 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

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.

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: 8

🧹 Nitpick comments (3)
shared/schemas/github.ts (1)

3-6: Consider adding non-empty string validation for owner and repo.

v.string() accepts empty strings, which would pass validation but fail silently at the GitHub API level. A minLength(1) pipe rejects these at the schema boundary.

♻️ Suggested fix
 export const GitHubStarBodySchema = v.object({
-  owner: v.string(),
-  repo: v.string(),
+  owner: v.pipe(v.string(), v.minLength(1)),
+  repo: v.pipe(v.string(), v.minLength(1)),
 })
server/api/auth/github/session.delete.ts (1)

3-11: Consider returning a structured JSON response for consistency.

Other endpoints in this PR return JSON objects (e.g., { starred: false }). Returning a plain string here makes it harder for clients to handle responses uniformly. A minor inconsistency, but worth aligning.

Suggested fix
-  return 'GitHub disconnected'
+  return { disconnected: true }
server/api/github/star.put.ts (1)

7-47: Significant code duplication with star.delete.ts.

This handler is nearly identical to star.delete.ts — the only differences are the HTTP method (PUT vs DELETE), the Content-Length header, and the returned starred boolean. Consider extracting a shared helper to reduce duplication:

Sketch of shared helper
// server/utils/github-star.ts
export async function toggleGitHubStar(event: H3Event, method: 'PUT' | 'DELETE') {
  const session = await useServerSession(event)
  const github = session.data.github

  if (!github?.accessToken) {
    throw createError({ statusCode: 401, message: 'GitHub account not connected.' })
  }

  const { owner, repo } = v.parse(GitHubStarBodySchema, await readBody(event))

  // ... validation, fetch, error handling ...

  return { starred: method === 'PUT' }
}

Note: the path traversal concern flagged on star.delete.ts applies equally here.


ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0fd5a7d and 4497ac5.

📒 Files selected for processing (24)
  • app/components/Header/AccountMenu.client.vue
  • app/components/Header/AtprotoModal.client.vue
  • app/components/Header/GitHubModal.client.vue
  • app/composables/atproto/useAtproto.ts
  • app/composables/github/useGitHub.ts
  • app/composables/github/useGitHubStar.ts
  • app/pages/package/[[org]]/[name].vue
  • i18n/locales/en.json
  • i18n/schema.json
  • lunaria/files/en-GB.json
  • lunaria/files/en-US.json
  • nuxt.config.ts
  • server/api/auth/atproto/index.get.ts
  • server/api/auth/atproto/session.delete.ts
  • server/api/auth/atproto/session.get.ts
  • server/api/auth/github/index.get.ts
  • server/api/auth/github/session.delete.ts
  • server/api/auth/github/session.get.ts
  • server/api/github/star.delete.ts
  • server/api/github/star.put.ts
  • server/api/github/starred.get.ts
  • server/utils/auth.ts
  • shared/schemas/github.ts
  • shared/types/userSession.ts

Comment on lines 893 to 916
<TooltipApp
v-if="isGitHubRepo && isGitHubConnected"
:text="
isStarred ? $t('package.github_star.unstar') : $t('package.github_star.star')
"
position="bottom"
strategy="fixed"
>
<ButtonBase
size="small"
:title="
isStarred ? $t('package.github_star.unstar') : $t('package.github_star.star')
"
:aria-label="
isStarred ? $t('package.github_star.unstar') : $t('package.github_star.star')
"
:aria-pressed="isStarred"
:disabled="isStarActionPending"
:classicon="isStarred ? 'i-lucide:star text-yellow-400' : 'i-lucide:star'"
@click="toggleStar"
>
{{ compactNumberFormatter.format(stars) }}
</ButtonBase>
</TooltipApp>
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

Star count does not update after toggling.

stars (Line 914) comes from useRepoMeta, which fetches the repository metadata once. After toggleStar, isStarred updates via the optimistic UI in useGitHubStar, but stars remains stale — the count won't increment/decrement. This creates a confusing UX where the icon changes but the number doesn't.

Consider deriving a display count that adjusts based on the toggle delta:

const displayStars = computed(() => {
  if (!isGitHubConnected.value) return stars.value
  // Adjust based on the original fetched state vs current toggled state
  // (requires tracking the initial starred state from the API)
  ...
})

Alternatively, pass the stars value into useGitHubStar so it can return a reactive adjusted count.

@serhalp serhalp linked an issue Feb 23, 2026 that may be closed by this pull request
@serhalp serhalp added the social Social features label Feb 23, 2026
@olivermrose
Copy link
Contributor Author

olivermrose commented Feb 23, 2026

Was attempting to update the star count, but it seems like GitHub's api doesn't immediately update. I can optimistically update the UI, but I'm not sure how to persist the star count on refresh/navigate (or if this even a priority).

@olivermrose olivermrose marked this pull request as draft February 23, 2026 20:48
@olivermrose

This comment was marked as resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

social Social features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

github connection

2 participants