Skip to content

Conversation

@ASR1015
Copy link
Contributor

@ASR1015 ASR1015 commented Aug 13, 2025

Related Issue
Closes #89

Description

This PR refactors the data fetching logic for GitHub issues and PRs to use a central searchUserIssuesAndPRs helper for pagination.
Previously, direct search calls were limited by GitHub’s 1000 results cap, causing missing data for users with high activity.
The updated implementation uses robust date-window pagination, ensuring all results are fetched without hitting the cap.

Key changes:
• Removed duplicate search logic from individual hooks
• Integrated searchUserIssuesAndPRs in useGitHubData for both issues & PRs
• Implemented client-side slicing for requested pages after fetching the complete dataset
• Improved rate-limit error handling

How Has This Been Tested?
• Ran npm run dev locally and tested with accounts exceeding 1000 results
• Verified pagination returns all expected results for both issues & PRs
• Confirmed UI loads correct results per page without truncation

Type of Change
• Bug fix
• New feature
• Code style update
• Breaking change
• Documentation update

Summary by CodeRabbit

  • New Features

    • Framework-agnostic GitHub search returning complete, deduplicated results with newest-first sorting.
    • Token-first data hook (env or user token) with client-side pagination over fully-fetched results.
    • Contributor profile: PR list improvements, merged badge, shareable link copy with clipboard support and toasts.
  • Bug Fixes

    • Cancellable fetches, rate-limit detection/retries, throttling/backoff, and safer handling of missing repo data.
  • Chores

    • Dev-friendly build/server defaults for easier local LAN previews.

@netlify
Copy link

netlify bot commented Aug 13, 2025

Deploy Preview for github-spy ready!

Name Link
🔨 Latest commit 7be569b
🔍 Latest deploy log https://app.netlify.com/projects/github-spy/deploys/689d930d14548900085a6529
😎 Deploy Preview https://deploy-preview-191--github-spy.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 13, 2025

Walkthrough

Adds a new GitHub search helper that paginates by date windows to bypass the 1000-result cap, with rate-limit/retry handling; refactors the data hook to use token-based fetching and client-side pagination; updates ContributorProfile to use the helper with abortable requests and improved UX.

Changes

Cohort / File(s) Summary
Search helper library
library/githubSearch.ts
New framework-agnostic search utility with types (GitHubSearchItem, SearchMode), internal GitHub API wrapper (rate-limit handling, retries), date-window bisecting to bypass 1000-result cap, batched requests (per_page=100), throttling, and exported APIs searchUserIssuesAndPRs and fetchUserItems.
Data hook refactor
src/hooks/useGitHubData.ts
Hook signature changed to token-first (removed getOctokit param); reads token from env or caller, uses searchUserIssuesAndPRs for concurrent fetches, implements client-side pagination over fully fetched results, AbortSignal support, rate-limit/error state, and adds default export.
Contributor profile integration
src/pages/ContributorProfile/ContributorProfile.tsx
Replaced direct fetch with searchUserIssuesAndPRs, added token-aware user fetch with headers, AbortController cancellation, loading/error toasts, clipboard copy fallback, guarded rendering, and PR list rendering using GitHubSearchItem.
Build config (unrelated)
vite.config.ts
Vite config expanded with target/sourcemap conditional, manualChunks, server/preview host:true, resolve dedupe, and optimizeDeps includes; no public API changes.

Sequence Diagram(s)

sequenceDiagram
  participant UI as ContributorProfile
  participant Hook as useGitHubData
  participant Lib as githubSearch.searchUserIssuesAndPRs
  participant GH as GitHub API

  UI->>Hook: fetchData(username, page, perPage, state, signal)
  Hook->>Lib: searchUserIssuesAndPRs({ username, mode, token, state, start, end, signal })
  Lib->>GH: GET /search/issues?q=...&per_page=100 (date-windowed)
  GH-->>Lib: Results (+ rate-limit headers / errors)
  Lib->>Lib: Retry/backoff or bisect date window if total > 1000
  Lib-->>Hook: Deduped, sorted items
  Hook-->>UI: totals and client-side paginated slice
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Assessment against linked issues

Objective Addressed Explanation
Fix pagination failures for some users by ensuring complete retrieval beyond API caps (#89)
Handle rate limiting and retries to improve data fetch robustness related to pagination issues (#89)
Maintain correct totals and page slicing for issues and PRs in UI (#89)

Out-of-scope changes

Code Change Explanation
Vite config updates (vite.config.ts) Build/dev server and bundling config changes are unrelated to the pagination/rate-limit objectives in #89.

Possibly related PRs

Suggested labels

level2

Poem

I nibbled through the date-range hedge,
Hopped past the thousand-result ledge,
Tokens snug, retries in flight,
I gathered PRs into the night,
Now pages hop along just right — 🐇✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7c5516e and 7be569b.

📒 Files selected for processing (1)
  • src/pages/ContributorProfile/ContributorProfile.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/pages/ContributorProfile/ContributorProfile.tsx
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • 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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@ASR1015
Copy link
Contributor Author

ASR1015 commented Aug 13, 2025

This PR addresses #89 by implementing central pagination handling via searchUserIssuesAndPRs. Tested with accounts exceeding the 1000-item search cap, and verified UI loads complete data. Ready for review.

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

🧹 Nitpick comments (6)
library/githubSearch.ts (3)

49-52: Improve rate limit handling precision

The current implementation adds a fixed 1000ms buffer to the rate limit reset time, but this might be insufficient if there's clock skew between client and server.

     if (resp.status === 403) {
       const reset = Number(resp.headers.get("X-RateLimit-Reset") || "0") * 1000;
-      const waitMs = Math.max(0, reset - Date.now()) + 1000;
+      // Add 2 seconds buffer to account for clock skew and network latency
+      const waitMs = Math.max(0, reset - Date.now()) + 2000;
       if (waitMs > 0) await sleep(waitMs);

145-149: Optimize deduplication logic

The current deduplication uses a comma operator which is less readable. Consider a clearer approach.

   // de-dupe and sort newest-first
   const seen = new Set<number>();
-  const unique = results.filter((it) => (seen.has(it.id) ? false : (seen.add(it.id), true)));
+  const unique = results.filter((it) => {
+    if (seen.has(it.id)) return false;
+    seen.add(it.id);
+    return true;
+  });
   unique.sort((a, b) => b.created_at.localeCompare(a.created_at));
   return unique;

165-170: Improve environment variable access safety

The current implementation uses multiple any casts and property access that could fail. Consider a safer approach.

   const token =
     (opts.userProvidedToken && opts.userProvidedToken.trim()) ||
-    (typeof import.meta !== "undefined" &&
-    (import.meta as any).env &&
-    (import.meta as any).env.VITE_GITHUB_TOKEN) ||
+    (typeof import.meta !== "undefined" &&
+     import.meta.env?.VITE_GITHUB_TOKEN as string | undefined) ||
     undefined;
src/pages/ContributorProfile/ContributorProfile.tsx (2)

19-20: Avoid redundant loading state update

setLoading(true) is called when loading is already true by default (line 10), making this redundant on the first render.

-      setLoading(true);
       toastId = toast.loading("Fetching PRs…");

100-100: Potential runtime error with repository_url access

While optional chaining is used, the fallback to empty string could cause issues. Consider extracting just the repository name instead of the full path.

-            const repoName = pr.repository_url?.split("/").slice(-2).join("/") ?? "";
+            const repoName = pr.repository_url?.split("/").pop() ?? "Unknown";

This extracts just the repository name rather than "owner/repo" format, which might be cleaner for display.

src/hooks/useGitHubData.ts (1)

17-26: Consider using a more reliable token reading approach

The current implementation catches all errors silently, which could hide legitimate issues. Also, the eslint disable comment suggests this approach might not be ideal.

   const readToken = (): string | undefined => {
-    try {
-      // Vite exposes env under import.meta.env
-      // eslint-disable-next-line @typescript-eslint/no-explicit-any
-      const env = (import.meta as any)?.env as Record<string, string> | undefined;
-      return env?.VITE_GITHUB_TOKEN || undefined;
-    } catch {
-      return undefined;
-    }
+    // Safe access to Vite environment variables
+    if (typeof import.meta !== 'undefined' && import.meta.env) {
+      return import.meta.env.VITE_GITHUB_TOKEN as string | undefined;
+    }
+    return undefined;
   };
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 00a00d6 and 3f8e375.

📒 Files selected for processing (3)
  • library/githubSearch.ts (1 hunks)
  • src/hooks/useGitHubData.ts (2 hunks)
  • src/pages/ContributorProfile/ContributorProfile.tsx (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
src/pages/ContributorProfile/ContributorProfile.tsx (2)
library/githubSearch.ts (1)
  • searchUserIssuesAndPRs (117-150)
src/pages/Tracker/Tracker.tsx (1)
  • GitHubItem (38-46)
library/githubSearch.ts (1)
src/pages/Tracker/Tracker.tsx (4)
  • GitHubItem (38-46)
  • theme (48-342)
  • item (295-323)
  • item (104-107)
src/hooks/useGitHubData.ts (3)
library/githubSearch.ts (1)
  • searchUserIssuesAndPRs (117-150)
src/hooks/useGitHubAuth.ts (3)
  • username (4-25)
  • octokit (14-14)
  • username (9-12)
src/pages/Tracker/Tracker.tsx (1)
  • GitHubItem (38-46)
🔇 Additional comments (2)
src/pages/ContributorProfile/ContributorProfile.tsx (1)

60-63: Good implementation of cleanup logic

The cancellation mechanism and toast cleanup in the useEffect return function properly prevents state updates after unmount and cleans up UI indicators.

src/hooks/useGitHubData.ts (1)

39-42: Good use of parallel fetching

The implementation correctly uses Promise.all to fetch issues and PRs concurrently, improving performance compared to sequential requests.

@ASR1015
Copy link
Contributor Author

ASR1015 commented Aug 14, 2025

All review suggestions have been implemented. Marking this PR as ready for merge.

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

♻️ Duplicate comments (3)
src/hooks/useGitHubData.ts (3)

41-43: Good pagination validation

The validation for page and perPage parameters prevents invalid array slicing operations downstream.


51-55: Rate limit handling provides clear user feedback

Setting a specific error message when rate-limited ensures users understand why the request failed.


73-76: Client-side pagination correctly implemented

The slicing logic with proper index calculations effectively implements client-side pagination on the fully-fetched results.

🧹 Nitpick comments (3)
vite.config.ts (1)

10-30: Consider allowing source maps in development builds

While disabling source maps in production is reasonable for performance and security, the sourcemap: false setting applies to all builds. Consider enabling source maps conditionally for development builds to aid debugging.

 build: {
   target: "es2020",
-  sourcemap: false,               // no source maps in prod build
+  sourcemap: process.env.NODE_ENV === 'development',  // source maps only in dev
   cssCodeSplit: true,             // keep CSS split for better caching

Alternatively, you can use Vite's mode-based configuration:

-  sourcemap: false,
+  sourcemap: process.env.NODE_ENV !== 'production',
src/hooks/useGitHubData.ts (1)

84-92: Consider more specific rate limit detection

The current rate limit detection using string matching on "rate limit" or "403" might produce false positives. Consider checking for more specific GitHub API rate limit responses.

GitHub's rate limit errors typically include specific headers and status codes. Consider enhancing the detection:

-        if (msg.toLowerCase().includes("rate limit") || msg.includes("403")) {
+        // GitHub returns 403 with specific rate limit message
+        if (msg.toLowerCase().includes("rate limit") || 
+            msg.includes("API rate limit exceeded") ||
+            (msg.includes("403") && msg.toLowerCase().includes("limit"))) {
           setRateLimited(true);
         }
src/pages/ContributorProfile/ContributorProfile.tsx (1)

145-145: Add null check for repository_url parsing

While optional chaining is used, consider adding explicit validation to handle edge cases where repository_url might be malformed.

-            const repoName = pr.repository_url?.split("/").slice(-2).join("/") ?? "";
+            const repoName = pr.repository_url && pr.repository_url.includes("/") 
+              ? pr.repository_url.split("/").slice(-2).join("/") 
+              : "unknown";
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3f8e375 and 1eff568.

📒 Files selected for processing (4)
  • library/githubSearch.ts (1 hunks)
  • src/hooks/useGitHubData.ts (2 hunks)
  • src/pages/ContributorProfile/ContributorProfile.tsx (3 hunks)
  • vite.config.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • library/githubSearch.ts
🧰 Additional context used
🧬 Code Graph Analysis (3)
vite.config.ts (1)
src/vite-env.d.ts (2)
  • ImportMetaEnv (3-6)
  • ImportMeta (8-10)
src/pages/ContributorProfile/ContributorProfile.tsx (1)
src/pages/Tracker/Tracker.tsx (1)
  • GitHubItem (38-46)
src/hooks/useGitHubData.ts (2)
src/hooks/useGitHubAuth.ts (3)
  • username (4-25)
  • octokit (14-14)
  • username (9-12)
src/pages/Tracker/Tracker.tsx (1)
  • GitHubItem (38-46)
🔇 Additional comments (12)
vite.config.ts (4)

21-27: Manual chunks configuration looks good

The chunking strategy effectively separates React core, router, and vendor dependencies for optimal caching. The function-based approach correctly avoids Vite warnings.


33-39: HMR overlay configuration is properly documented

Good documentation explaining how to control the error overlay during development. The default true setting is appropriate for most development scenarios.


46-48: React deduplication prevents version conflicts

The deduplication of React and React DOM is crucial for preventing the "multiple React instances" error that can occur when dependencies have their own React versions. This is especially important with the new GitHub data fetching architecture.


50-53: Pre-bundling configuration optimizes cold starts

Including React, React DOM, and React Router DOM in optimizeDeps ensures these core dependencies are pre-bundled during dev server startup, significantly improving cold start performance.

src/hooks/useGitHubData.ts (2)

16-26: Secure token access implementation

The readToken function safely accesses the environment variable with proper error handling. The try-catch block prevents runtime errors if import.meta is unavailable, and the defensive approach with optional chaining is appropriate.


58-83: Robust request cancellation pattern

The implementation correctly handles both external and internal abort signals, ensuring proper cleanup to prevent memory leaks and state updates on unmounted components. The finally block appropriately aborts only internally-created controllers.

src/pages/ContributorProfile/ContributorProfile.tsx (6)

21-24: Well-structured cleanup tracking

Good use of controller for AbortSignal, canceled flag for additional safety, and toastId for proper toast cleanup. This prevents race conditions and ensures clean component unmounting.


33-43: Token authentication properly implemented

The token is correctly retrieved from environment variables and conditionally added to headers. The use of spread operator for conditional header inclusion is clean and follows best practices.


44-51: Comprehensive error handling for user fetch

Excellent handling of different error scenarios - specifically checking for 404 to provide user-friendly "User not found" messages while also handling other HTTP errors appropriately.


57-65: Efficient PR fetching with proper cancellation checks

The migration to searchUserIssuesAndPRs centralizes pagination logic effectively. The post-fetch sorting by updated_at ensures recent PRs appear first, and the cancellation check prevents state updates after unmount.


91-108: Clipboard API with fallback implementation

Excellent implementation using the modern Clipboard API with a fallback for older browsers. The async/await pattern with proper error handling and user feedback via toasts is well done.


155-157: Merged PR badge implementation

Good visual indicator for merged PRs using conditional rendering and appropriate styling with dark mode support.

@ASR1015
Copy link
Contributor Author

ASR1015 commented Aug 14, 2025

All nitpicks addressed, ready to merge

@ASR1015
Copy link
Contributor Author

ASR1015 commented Aug 14, 2025

Refactor: centralize GitHub search helper and improve safety checks

  • Use central githubSearch helper for issues & PRs pagination
  • Enable source maps only in development for better debugging
  • Improve GitHub API rate limit detection to reduce false positives
  • Add null check for repository_url parsing to prevent runtime errors
  • Address all CodeRabbit review nitpicks for cleaner, more maintainable code

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

♻️ Duplicate comments (1)
src/pages/ContributorProfile/ContributorProfile.tsx (1)

16-16: Type-safety improvement acknowledged.

Switching prs to GitHubSearchItem[] aligns with searchUserIssuesAndPRs and resolves the earlier regression.

🧹 Nitpick comments (3)
src/pages/ContributorProfile/ContributorProfile.tsx (3)

56-65: Document the custom sort criteria (updated_at vs created_at).

searchUserIssuesAndPRs returns items sorted by created_at; here you re-sort by updated_at. Add a brief comment to avoid future confusion.

Apply this diff:

-        setPRs([...prItems].sort((a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime()));
+        // Sort by last update time to surface the most recent activity
+        setPRs([...prItems].sort((a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime()));

91-107: Clipboard fallback: hide the temporary textarea to avoid layout shifts.

Moving the textarea off-screen prevents jank and accidental scrolling during selection.

Apply this diff:

-        const el = document.createElement("textarea");
-        el.value = window.location.href;
-        document.body.appendChild(el);
-        el.select();
-        document.execCommand("copy");
-        document.body.removeChild(el);
+        const el = document.createElement("textarea");
+        el.value = window.location.href;
+        el.setAttribute("readonly", "");
+        el.style.position = "fixed";
+        el.style.top = "-9999px";
+        document.body.appendChild(el);
+        el.select();
+        el.setSelectionRange(0, el.value.length);
+        document.execCommand("copy");
+        document.body.removeChild(el);

121-126: A11y: Provide a more descriptive alt text for the avatar.

Improves screen reader context.

Apply this diff:

-          alt="Avatar"
+          alt={`${profile.login}'s avatar`}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1eff568 and 828460d.

📒 Files selected for processing (3)
  • src/hooks/useGitHubData.ts (2 hunks)
  • src/pages/ContributorProfile/ContributorProfile.tsx (3 hunks)
  • vite.config.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/hooks/useGitHubData.ts
  • vite.config.ts
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/pages/ContributorProfile/ContributorProfile.tsx (2)
library/githubSearch.ts (2)
  • GitHubSearchItem (6-17)
  • searchUserIssuesAndPRs (128-162)
src/pages/Tracker/Tracker.tsx (1)
  • GitHubItem (38-46)
🔇 Additional comments (1)
src/pages/ContributorProfile/ContributorProfile.tsx (1)

81-88: Cleanup is solid: aborts pending requests and dismisses toasts.

Good use of AbortController, canceled guard, and toast cleanup to prevent setState-on-unmounted and stray toasts.

@ASR1015
Copy link
Contributor Author

ASR1015 commented Aug 14, 2025

All suggested changes have been applied

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

🔭 Outside diff range comments (1)
src/pages/ContributorProfile/ContributorProfile.tsx (1)

121-125: Don't hide non-404 errors: early return masks errorMsg when profile is null

If the profile fetch fails due to rate limits or network errors, profile remains null but the UI always shows "User not found.", hiding the actual error stored in errorMsg. Make the early-return render errorMsg when present.

Apply this diff:

-  if (!profile)
-    return (
-      <div className="text-center mt-10 text-red-600">User not found.</div>
-    );
+  if (!profile) {
+    return (
+      <div className="text-center mt-10 text-red-600">
+        {errorMsg ?? "User not found."}
+      </div>
+    );
+  }
♻️ Duplicate comments (1)
src/pages/ContributorProfile/ContributorProfile.tsx (1)

26-31: Good fix: prevent indefinite loading when username is missing

Early-return now resets loading and surfaces a helpful error message. This avoids a stuck "Loading..." UI.

🧹 Nitpick comments (2)
src/pages/ContributorProfile/ContributorProfile.tsx (2)

50-56: Improve rate-limit error messaging for user profile fetch (403)

When the user request is rate-limited (403), the current message is generic. Offer a clearer message and hint for dev token usage.

Apply this diff:

-        if (!userRes.ok) {
-          if (userRes.status === 404) {
-            setProfile(null);
-            throw new Error("User not found");
-          }
-          throw new Error(`Failed to fetch user: ${userRes.status}`);
-        }
+        if (!userRes.ok) {
+          if (userRes.status === 404) {
+            setProfile(null);
+            throw new Error("User not found");
+          }
+          if (userRes.status === 403) {
+            const rem = userRes.headers.get("x-ratelimit-remaining");
+            const msg =
+              rem === "0"
+                ? "GitHub API rate limit exceeded. Please try again later."
+                : "Access forbidden. If in development, set VITE_GITHUB_TOKEN.";
+            throw new Error(msg);
+          }
+          throw new Error(`Failed to fetch user: ${userRes.status}`);
+        }

153-156: Repository name derivation is safe; consider URL parsing for clarity (optional)

Current split logic works; a URL parse is slightly more robust and self-documenting.

Apply this diff:

-            const repoName = pr.repository_url && pr.repository_url.includes("/")
-              ? pr.repository_url.split("/").slice(-2).join("/")
-              : "unknown";
+            const repoName = (() => {
+              if (!pr.repository_url) return "unknown";
+              try {
+                const url = new URL(pr.repository_url);
+                const parts = url.pathname.split("/").filter(Boolean);
+                return parts.slice(-2).join("/");
+              } catch {
+                return "unknown";
+              }
+            })();
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 828460d and 7c5516e.

📒 Files selected for processing (1)
  • src/pages/ContributorProfile/ContributorProfile.tsx (3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/pages/ContributorProfile/ContributorProfile.tsx (2)
library/githubSearch.ts (2)
  • GitHubSearchItem (6-17)
  • searchUserIssuesAndPRs (128-162)
src/pages/Tracker/Tracker.tsx (1)
  • GitHubItem (38-46)
🔇 Additional comments (3)
src/pages/ContributorProfile/ContributorProfile.tsx (3)

37-39: Token gated to dev builds — avoids shipping secrets

Reading VITE_GITHUB_TOKEN only when import.meta.env.DEV is true prevents leaking a PAT in production bundles.


21-24: Solid abort/cancel discipline

Using AbortController, a canceled flag, and ignoring AbortError prevents spurious error toasts and state updates after unmount/navigation.

Also applies to: 71-79, 80-85


4-4: Import path is correct — no change required.

Verified that library/githubSearch.ts exists at the repository root and the import in src/pages/ContributorProfile/ContributorProfile.tsx correctly resolves to it.

  • Found file: library/githubSearch.ts
  • Import (src/pages/ContributorProfile/ContributorProfile.tsx:4): import { searchUserIssuesAndPRs, GitHubSearchItem } from "../../../library/githubSearch";

@ASR1015
Copy link
Contributor Author

ASR1015 commented Aug 16, 2025

I’ve incorporated the suggested changes in commit 7be569b and confirmed that all checks have passed with no merge conflicts. The PR should now be good to go

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🐛 Bug Report: Pagination fails for some users

1 participant