-
Notifications
You must be signed in to change notification settings - Fork 202
feat: add GitHub repository comparison feature with side-by-side analytics #540
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,176 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { useState } from "react"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type RepoData = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| full_name: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| stargazers_count: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| forks_count: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| open_issues_count: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| watchers_count: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| language: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| updated_at: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const RepoCompare = () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [repo1, setRepo1] = useState(""); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [repo2, setRepo2] = useState(""); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [data1, setData1] = useState<RepoData | null>(null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [data2, setData2] = useState<RepoData | null>(null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [loading, setLoading] = useState(false); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [error, setError] = useState(""); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const fetchRepo = async (repo: string): Promise<RepoData> => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const res = await fetch(`https://api.github.com/repos/${repo}`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!res.ok) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw new Error(`Repository not found: ${repo}`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return res.json(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const handleCompare = async () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!repo1 || !repo2) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setError("Please enter both repositories"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setLoading(true); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setError(""); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [r1, r2] = await Promise.all([ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fetchRepo(repo1), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fetchRepo(repo2), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setData1(r1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setData2(r2); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (err: any) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setError(err.message || "Something went wrong"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+51
to
+52
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π§© Analysis chainπ Script executed: #!/bin/bash
# Verify explicit-any usage and lint rule presence.
rg -n --type=ts --type=tsx 'catch\s*\(\s*[^)]*:\s*any\s*\)'
rg -n '`@typescript-eslint/no-explicit-any`' .Repository: GitMetricsLab/github_tracker Length of output: 100 π Script executed: #!/bin/bash
set -euo pipefail
# 1) Inspect the target file around the referenced lines
echo "=== RepoCompare.tsx lines 40-80 ==="
nl -ba src/pages/RepoCompare/RepoCompare.tsx | sed -n '40,80p'
# 2) Find explicit-any in catch clauses (avoid invalid --type=tsx)
echo "=== catch (..: any) occurrences ==="
rg -n "catch\s*\(\s*[^)]*\s:\s*any\s*\)" -S . || true
# 3) Check whether `@typescript-eslint/no-explicit-any` exists in ESLint config
echo "=== `@typescript-eslint/no-explicit-any` occurrences ==="
rg -n "`@typescript-eslint/no-explicit-any`" -S . || true
# 4) List likely ESLint config files to understand whether the rule is enabled
echo "=== ESLint config files ==="
fd -a -t f -e js -e cjs -e mjs -e json -e yaml -e yml -e ts \
.eslintrc .eslintrc.* eslint.config .eslintignore package.json 2>/dev/null || trueRepository: GitMetricsLab/github_tracker Length of output: 169 π Script executed: #!/bin/bash
set -euo pipefail
echo "=== command availability ==="
command -v rg >/dev/null && echo "rg: ok" || echo "rg: missing"
command -v fd >/dev/null && echo "fd: ok" || echo "fd: missing"
command -v find >/dev/null && echo "find: ok" || echo "find: missing"
command -v cat >/dev/null && echo "cat: ok" || echo "cat: missing"
command -v sed >/dev/null && echo "sed: ok" || echo "sed: missing"
command -v head >/dev/null && echo "head: ok" || echo "head: missing"
# 1) Inspect the target file around the referenced lines
echo "=== RepoCompare.tsx lines 40-80 ==="
if [ -f "src/pages/RepoCompare/RepoCompare.tsx" ]; then
cat -n src/pages/RepoCompare/RepoCompare.tsx | sed -n '40,90p'
else
echo "Missing file: src/pages/RepoCompare/RepoCompare.tsx"
fi
# 2) Find explicit-any in catch clauses (avoid invalid --type=tsx)
echo "=== catch (...: any) occurrences ==="
rg -n "catch\s*\(\s*[^)]*\s:\s*any\s*\)" -S . || true
# 3) Check whether `@typescript-eslint/no-explicit-any` exists in ESLint config
echo "=== `@typescript-eslint/no-explicit-any` occurrences ==="
rg -n "`@typescript-eslint/no-explicit-any`" -S . || true
# 4) List likely ESLint config files to understand whether the rule is enabled
echo "=== ESLint config files ==="
# Prefer fd if available, otherwise fallback to find
if command -v fd >/dev/null; then
fd -a -t f -e js -e cjs -e mjs -e json -e yaml -e yml -e ts \
.eslintrc .eslintrc.* eslint.config .eslintignore package.json 2>/dev/null || true
else
find . -maxdepth 4 -type f \( \
-name ".eslintrc" -o -name ".eslintrc.*" -o -name "eslint.config.*" -o -name ".eslintignore" \
-o -name "package.json" \
\) 2>/dev/null || true
fi
# 5) If we found ESLint config file candidates, print the smallest relevant sections around the rule (if any)
echo "=== Snippets around rule in ESLint configs (if present) ==="
rg -n "`@typescript-eslint/no-explicit-any`" -S . -g'*.js' -g'*.cjs' -g'*.mjs' -g'*.json' -g'*.ts' -g'*.yml' -g'*.yaml' 2>/dev/null || trueRepository: GitMetricsLab/github_tracker Length of output: 2005 π Script executed: #!/bin/bash
set -euo pipefail
echo "=== Files matching eslint config names ==="
fd -a -t f -e js -e cjs -e mjs -e json -e yaml -e yml -e ts \
'.eslintrc' '.eslintrc.*' 'eslint.config.*' '.eslintignore' -H . 2>/dev/null || true
echo "=== Find eslint / typescript-eslint in package.json ==="
if [ -f package.json ]; then
cat package.json | head -n 120
echo "=== grep devDependencies/scripts for eslint ==="
rg -n '"(eslint|typescript-eslint|`@typescript-eslint`)/' package.json || true
rg -n 'eslint' package.json || true
else
echo "Missing package.json"
fi
echo "=== Search for eslint configs and plugin usage ==="
rg -n "eslint\.config|no-explicit-any|`@typescript-eslint`" -S . || trueRepository: GitMetricsLab/github_tracker Length of output: 2714 π Script executed: #!/bin/bash
set -euo pipefail
echo "=== eslint.config.js ==="
if [ -f eslint.config.js ]; then
cat -n eslint.config.js | sed -n '1,200p'
else
echo "Missing eslint.config.js"
fi
echo "=== no-explicit-any references ==="
rg -n "no-explicit-any" -S . || true
echo "=== occurrences of ': any' in ts/tsx ==="
rg -n ":\s*any\b" --glob '*.{ts,tsx}' -S . || trueRepository: GitMetricsLab/github_tracker Length of output: 1231 π Web query:
π‘ Result: No. Citations:
Replace
Suggested fix- } catch (err: any) {
- setError(err.message || "Something went wrong");
+ } catch (err: unknown) {
+ setError(err instanceof Error ? err.message : "Something went wrong");
} finally {π§° Toolsπͺ ESLint[error] 51-51: Unexpected any. Specify a different type. ( π€ Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } finally { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+40
to
+53
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Clear previous comparison data when a new request fails. If a compare attempt fails, old Suggested fix try {
setLoading(true);
setError("");
+ setData1(null);
+ setData2(null);
@@
- } catch (err: any) {
+ } catch (err: any) {
setError(err.message || "Something went wrong");
} finally {π Committable suggestion
Suggested change
π§° Toolsπͺ ESLint[error] 51-51: Unexpected any. Specify a different type. ( π€ Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setLoading(false); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const formatDate = (date: string) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return new Date(date).toLocaleDateString(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div style={{ padding: "20px", maxWidth: "1000px", margin: "auto" }}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <h1 style={{ textAlign: "center" }}>π GitHub Repo Comparison</h1> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {/* INPUT SECTION */} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div style={{ display: "flex", gap: "10px", marginBottom: "20px" }}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <input | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type="text" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| placeholder="e.g. facebook/react" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value={repo1} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onChange={(e) => setRepo1(e.target.value)} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| style={{ flex: 1, padding: "10px" }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <input | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type="text" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| placeholder="e.g. vuejs/core" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value={repo2} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onChange={(e) => setRepo2(e.target.value)} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| style={{ flex: 1, padding: "10px" }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <button onClick={handleCompare} style={{ padding: "10px 20px" }}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Compare | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </button> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {/* ERROR */} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {error && ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div style={{ color: "red", marginBottom: "10px" }}>{error}</div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {/* LOADING */} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {loading && <p>Loading comparison...</p>} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {/* RESULT TABLE */} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {data1 && data2 && ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div style={{ overflowX: "auto" }}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <table | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| style={{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| width: "100%", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| borderCollapse: "collapse", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| textAlign: "center", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <thead> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <tr> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <th style={thStyle}>Metric</th> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <th style={thStyle}>{data1.full_name}</th> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <th style={thStyle}>{data2.full_name}</th> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </tr> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </thead> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <tbody> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <tr> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <td style={tdStyle}>β Stars</td> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <td style={tdStyle}>{data1.stargazers_count}</td> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <td style={tdStyle}>{data2.stargazers_count}</td> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </tr> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <tr> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <td style={tdStyle}>π΄ Forks</td> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <td style={tdStyle}>{data1.forks_count}</td> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <td style={tdStyle}>{data2.forks_count}</td> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </tr> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <tr> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <td style={tdStyle}>π Issues</td> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <td style={tdStyle}>{data1.open_issues_count}</td> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <td style={tdStyle}>{data2.open_issues_count}</td> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </tr> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <tr> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <td style={tdStyle}>π Watchers</td> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <td style={tdStyle}>{data1.watchers_count}</td> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <td style={tdStyle}>{data2.watchers_count}</td> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </tr> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <tr> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <td style={tdStyle}>π» Language</td> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <td style={tdStyle}>{data1.language}</td> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <td style={tdStyle}>{data2.language}</td> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </tr> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <tr> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <td style={tdStyle}>π Last Updated</td> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <td style={tdStyle}>{formatDate(data1.updated_at)}</td> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <td style={tdStyle}>{formatDate(data2.updated_at)}</td> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </tr> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <tr> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <td style={tdStyle}>π§Ύ Description</td> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <td style={tdStyle}>{data1.description}</td> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <td style={tdStyle}>{data2.description}</td> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </tr> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </tbody> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </table> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const thStyle: React.CSSProperties = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| border: "1px solid #ddd", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| padding: "10px", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| background: "#f4f4f4", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const tdStyle: React.CSSProperties = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| border: "1px solid #ddd", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| padding: "10px", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export default RepoCompare; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,18 @@ | ||||||||||||
| export async function fetchRepo(repo: string) { | ||||||||||||
| const normalizedRepo = repo.trim(); | ||||||||||||
| const res = await fetch(`https://api.github.com/repos/${normalizedRepo}`); | ||||||||||||
| if (!res.ok) { | ||||||||||||
| throw new Error(`Repository not found: ${normalizedRepo}`); | ||||||||||||
| } | ||||||||||||
| return res.json(); | ||||||||||||
|
PremDhakad07 marked this conversation as resolved.
|
||||||||||||
| } | ||||||||||||
| } | ||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove extra closing brace causing syntax error. Line 9 contains an extraneous closing brace that will prevent the code from compiling. π Fix for syntax error return res.json();
}
-}
export async function compareRepos(repo1: string, repo2: string) {π Committable suggestion
Suggested change
π§° Toolsπͺ Biome (2.4.15)[error] 9-9: Expected a statement but instead found '}'. (parse) π€ Prompt for AI Agents |
||||||||||||
|
|
||||||||||||
| export async function compareRepos(repo1: string, repo2: string) { | ||||||||||||
| const [a, b] = await Promise.all([ | ||||||||||||
| fetchRepo(repo1), | ||||||||||||
| fetchRepo(repo2), | ||||||||||||
| ]); | ||||||||||||
|
|
||||||||||||
| return { a, b }; | ||||||||||||
| } | ||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
π§© Analysis chain
π Web query:
In the GitHub REST API repository response, what is the semantic difference betweenwatchers_count,stargazers_count, andsubscribers_count, and which one represents actual watchers?π‘ Result:
In the GitHub REST API response, the semantic difference between these fields is as follows: subscribers_count represents the number of actual watchersβusers who are subscribed to receive notifications for activity in a repository [1][2]. watchers, watchers_count, and stargazers_count all represent the number of users who have starred a repository [1][2]. The confusion stems from a historical change made in 2012, where GitHub repurposed the "watching" functionality and introduced "starring" [1]. While the API terminology was maintained for backward compatibility, watchers_count and its related fields currently function as a count of stars, not repository subscribers [1][2]. If you need to identify users who are actively watching (subscribing) to a repository, you should use subscribers_count [3].
Citations:
π Script executed:
Repository: GitMetricsLab/github_tracker
Length of output: 115
π Script executed:
Repository: GitMetricsLab/github_tracker
Length of output: 4843
Fix βWatchersβ mapping (GitHub
watchers_countβ watchers/subscribers)The UI label βπ Watchersβ renders
watchers_count, but GitHub RESTβswatchers_count(likestargazers_count) is effectively the repoβs star count. Actual watchers aresubscribers_count. This will duplicate stars and misreport watcher analyticsβrendersubscribers_countfor βWatchersβ (or relabel the row as Stars-equivalent).Also applies to: 135-137
π€ Prompt for AI Agents