@chengyixu/gitpulse 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,74 @@
1
+ # gitpulse
2
+
3
+ Instant health check for any GitHub repository. Answers the question: **"Should I depend on this repo?"**
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install -g gitpulse
9
+ ```
10
+
11
+ Or run directly:
12
+
13
+ ```bash
14
+ npx gitpulse facebook/react
15
+ ```
16
+
17
+ ## What it shows
18
+
19
+ - **Activity Score** (0-100) — commits, PRs, and issues in the last 30 days
20
+ - **Bus Factor** — how many contributors do 80% of the commits
21
+ - **Health Metrics** — estimated first response time, PR merge time, issue close rate
22
+ - **Dependencies** — count of runtime and dev dependencies
23
+ - **Verdict** — one-line assessment: "Active & Healthy", "Declining", "Abandoned", etc.
24
+
25
+ ## Usage
26
+
27
+ ```bash
28
+ # Full report
29
+ gitpulse facebook/react
30
+
31
+ # Compact one-liner
32
+ gitpulse vercel/next.js --compact
33
+
34
+ # JSON output for scripting
35
+ gitpulse pallets/flask --json
36
+
37
+ # Also accepts full GitHub URLs
38
+ gitpulse https://github.com/denoland/deno
39
+ ```
40
+
41
+ ## Output example
42
+
43
+ ```
44
+ 💚 facebook/react — Active & Healthy
45
+ ────────────────────────────────────────────────────────
46
+ ⭐ 232,000 🔴 47,200 👁 6,700 📋 940 open issues
47
+ A JavaScript library for building user interfaces
48
+
49
+ ACTIVITY (last 30 days)
50
+ Score: ████████████████░░░░ 82/100
51
+ Commits: 147 (38 in last 7d)
52
+ PRs opened: 52
53
+ PRs merged: 41
54
+ ...
55
+
56
+ BUS FACTOR
57
+ Bus factor: 8 (1,842 total contributors)
58
+ ...
59
+
60
+ VERDICT: 💚 Active & Healthy
61
+ ```
62
+
63
+ ## Higher rate limits
64
+
65
+ By default, GitHub allows 60 API requests per hour for unauthenticated users. For higher limits (5,000/hr), set a token:
66
+
67
+ ```bash
68
+ export GITHUB_TOKEN=ghp_your_token_here
69
+ gitpulse facebook/react
70
+ ```
71
+
72
+ ## License
73
+
74
+ MIT
@@ -0,0 +1,41 @@
1
+ import { GitHubRepo } from "./github";
2
+ export interface ActivityMetrics {
3
+ commits7d: number;
4
+ commits30d: number;
5
+ prsOpened30d: number;
6
+ prsMerged30d: number;
7
+ issuesOpened30d: number;
8
+ issuesClosed30d: number;
9
+ activityScore: number;
10
+ }
11
+ export interface BusFactorResult {
12
+ busFactor: number;
13
+ topContributors: Array<{
14
+ login: string;
15
+ percentage: number;
16
+ }>;
17
+ totalContributors: number;
18
+ }
19
+ export interface HealthMetrics {
20
+ medianFirstResponseHours: number | null;
21
+ medianPRMergeHours: number | null;
22
+ issueCloseRate: number;
23
+ hasIssuesEnabled: boolean;
24
+ }
25
+ export interface DependencyFreshness {
26
+ totalDeps: number;
27
+ checked: boolean;
28
+ note: string;
29
+ }
30
+ export type Verdict = "Active & Healthy" | "Active but Understaffed" | "Slowing Down" | "Minimal Maintenance" | "Declining" | "Abandoned" | "Archived";
31
+ export interface PulseReport {
32
+ repo: GitHubRepo;
33
+ activity: ActivityMetrics;
34
+ busFactor: BusFactorResult;
35
+ health: HealthMetrics;
36
+ dependencies: DependencyFreshness;
37
+ verdict: Verdict;
38
+ verdictEmoji: string;
39
+ }
40
+ export declare function generatePulseReport(owner: string, repo: string): Promise<PulseReport>;
41
+ //# sourceMappingURL=analysis.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analysis.d.ts","sourceRoot":"","sources":["../src/analysis.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EAWX,MAAM,UAAU,CAAC;AAElB,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9D,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,aAAa;IAC5B,wBAAwB,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,OAAO,GACf,kBAAkB,GAClB,yBAAyB,GACzB,cAAc,GACd,qBAAqB,GACrB,WAAW,GACX,WAAW,GACX,UAAU,CAAC;AAEf,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,eAAe,CAAC;IAC1B,SAAS,EAAE,eAAe,CAAC;IAC3B,MAAM,EAAE,aAAa,CAAC;IACtB,YAAY,EAAE,mBAAmB,CAAC;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAkPD,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,WAAW,CAAC,CAuBtB"}
@@ -0,0 +1,198 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generatePulseReport = generatePulseReport;
4
+ const github_1 = require("./github");
5
+ function daysAgo(n) {
6
+ const d = new Date();
7
+ d.setDate(d.getDate() - n);
8
+ return d.toISOString();
9
+ }
10
+ function hoursBetween(a, b) {
11
+ return Math.abs(new Date(b).getTime() - new Date(a).getTime()) / (1000 * 60 * 60);
12
+ }
13
+ function median(values) {
14
+ if (values.length === 0)
15
+ return null;
16
+ const sorted = [...values].sort((a, b) => a - b);
17
+ const mid = Math.floor(sorted.length / 2);
18
+ return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
19
+ }
20
+ function computeActivityScore(m) {
21
+ // Weighted scoring: commits matter most, then PRs, then issues
22
+ let score = 0;
23
+ // commits in 30d: 0-40 points
24
+ score += Math.min(40, m.commits30d * 0.8);
25
+ // PRs merged in 30d: 0-25 points
26
+ score += Math.min(25, m.prsMerged30d * 2.5);
27
+ // PRs opened in 30d: 0-10 points
28
+ score += Math.min(10, m.prsOpened30d * 1);
29
+ // Issues activity: 0-15 points
30
+ score += Math.min(15, (m.issuesOpened30d + m.issuesClosed30d) * 0.5);
31
+ // Recency boost: commits in 7d: 0-10 points
32
+ score += Math.min(10, m.commits7d * 2);
33
+ return Math.min(100, Math.round(score));
34
+ }
35
+ async function analyzeActivity(owner, repo) {
36
+ const since30d = daysAgo(30);
37
+ const since7d = daysAgo(7);
38
+ const now = new Date().toISOString();
39
+ const [commits30d, issuesAll, prsClosed, prsOpen] = await Promise.all([
40
+ (0, github_1.fetchCommits)(owner, repo, since30d).catch(() => []),
41
+ (0, github_1.fetchIssues)(owner, repo, "all", since30d).catch(() => []),
42
+ (0, github_1.fetchPRs)(owner, repo, "closed", 100).catch(() => []),
43
+ (0, github_1.fetchPRs)(owner, repo, "open", 100).catch(() => []),
44
+ ]);
45
+ const commits7d = commits30d.filter((c) => new Date(c.commit.author.date) >= new Date(since7d)).length;
46
+ // Filter issues (not PRs)
47
+ const pureIssues = issuesAll.filter((i) => !i.pull_request);
48
+ const issuesOpened30d = pureIssues.filter((i) => new Date(i.created_at) >= new Date(since30d)).length;
49
+ const issuesClosed30d = pureIssues.filter((i) => i.closed_at && new Date(i.closed_at) >= new Date(since30d)).length;
50
+ // PRs in last 30d
51
+ const allPRs = [...prsClosed, ...prsOpen];
52
+ const prsOpened30d = allPRs.filter((p) => new Date(p.created_at) >= new Date(since30d)).length;
53
+ const prsMerged30d = prsClosed.filter((p) => p.merged_at && new Date(p.merged_at) >= new Date(since30d)).length;
54
+ const partial = {
55
+ commits7d,
56
+ commits30d: commits30d.length,
57
+ prsOpened30d,
58
+ prsMerged30d,
59
+ issuesOpened30d,
60
+ issuesClosed30d,
61
+ };
62
+ return {
63
+ ...partial,
64
+ activityScore: computeActivityScore(partial),
65
+ };
66
+ }
67
+ async function analyzeBusFactor(owner, repo) {
68
+ const contributors = await (0, github_1.fetchContributors)(owner, repo).catch(() => []);
69
+ if (contributors.length === 0) {
70
+ return { busFactor: 0, topContributors: [], totalContributors: 0 };
71
+ }
72
+ const total = contributors.reduce((sum, c) => sum + c.contributions, 0);
73
+ if (total === 0) {
74
+ return { busFactor: 0, topContributors: [], totalContributors: contributors.length };
75
+ }
76
+ // Find how many contributors make up 80% of commits
77
+ let cumulative = 0;
78
+ let busFactor = 0;
79
+ const topContributors = [];
80
+ for (const c of contributors) {
81
+ cumulative += c.contributions;
82
+ busFactor++;
83
+ topContributors.push({
84
+ login: c.login,
85
+ percentage: Math.round((c.contributions / total) * 100),
86
+ });
87
+ if (cumulative / total >= 0.8)
88
+ break;
89
+ }
90
+ return {
91
+ busFactor,
92
+ topContributors: topContributors.slice(0, 5),
93
+ totalContributors: contributors.length,
94
+ };
95
+ }
96
+ async function analyzeHealth(owner, repo, hasIssuesEnabled) {
97
+ const since90d = daysAgo(90);
98
+ const [closedIssues, closedPRs, allIssues] = await Promise.all([
99
+ (0, github_1.fetchIssues)(owner, repo, "closed", since90d).catch(() => []),
100
+ (0, github_1.fetchPRs)(owner, repo, "closed", 100).catch(() => []),
101
+ (0, github_1.fetchIssues)(owner, repo, "all", since90d).catch(() => []),
102
+ ]);
103
+ // Filter to pure issues (not PRs)
104
+ const pureClosedIssues = closedIssues.filter((i) => !i.pull_request);
105
+ const pureAllIssues = allIssues.filter((i) => !i.pull_request);
106
+ // Issue close rate
107
+ const issueCloseRate = pureAllIssues.length > 0
108
+ ? Math.round((pureClosedIssues.length / pureAllIssues.length) * 100)
109
+ : 0;
110
+ // First response time approximation: if issue has comments and was closed,
111
+ // we approximate first response as halfway between creation and close
112
+ // (GitHub API doesn't give us comment timestamps without extra calls)
113
+ const responseHours = [];
114
+ for (const issue of pureClosedIssues.slice(0, 30)) {
115
+ if (issue.comments > 0 && issue.closed_at) {
116
+ // Rough approximation: first response ~ 1/3 of total lifetime
117
+ const lifetime = hoursBetween(issue.created_at, issue.closed_at);
118
+ if (lifetime > 0) {
119
+ responseHours.push(lifetime * 0.33);
120
+ }
121
+ }
122
+ }
123
+ // PR merge time
124
+ const mergeHours = [];
125
+ for (const pr of closedPRs) {
126
+ if (pr.merged_at) {
127
+ const h = hoursBetween(pr.created_at, pr.merged_at);
128
+ if (h > 0)
129
+ mergeHours.push(h);
130
+ }
131
+ }
132
+ return {
133
+ medianFirstResponseHours: median(responseHours),
134
+ medianPRMergeHours: median(mergeHours),
135
+ issueCloseRate,
136
+ hasIssuesEnabled,
137
+ };
138
+ }
139
+ async function analyzeDependencies(owner, repo, branch) {
140
+ const pkg = await (0, github_1.fetchPackageJson)(owner, repo, branch);
141
+ if (!pkg) {
142
+ return { totalDeps: 0, checked: false, note: "No package.json found (not a JS/TS project, or private)" };
143
+ }
144
+ const deps = Object.keys(pkg.dependencies || {});
145
+ const devDeps = Object.keys(pkg.devDependencies || {});
146
+ const totalDeps = deps.length + devDeps.length;
147
+ if (totalDeps === 0) {
148
+ return { totalDeps: 0, checked: true, note: "No dependencies declared" };
149
+ }
150
+ return {
151
+ totalDeps,
152
+ checked: true,
153
+ note: `${deps.length} runtime + ${devDeps.length} dev dependencies found`,
154
+ };
155
+ }
156
+ function computeVerdict(repo, activity, busFactor, health) {
157
+ if (repo.archived)
158
+ return { verdict: "Archived", emoji: "\u{1F4E6}" };
159
+ const daysSinceLastPush = Math.round((Date.now() - new Date(repo.pushed_at).getTime()) / (1000 * 60 * 60 * 24));
160
+ if (daysSinceLastPush > 365 && activity.activityScore < 5) {
161
+ return { verdict: "Abandoned", emoji: "\u{1F480}" };
162
+ }
163
+ if (daysSinceLastPush > 180 || activity.activityScore < 10) {
164
+ return { verdict: "Declining", emoji: "\u{1F4C9}" };
165
+ }
166
+ if (activity.activityScore < 25) {
167
+ return { verdict: "Minimal Maintenance", emoji: "\u{1F6E0}\u{FE0F}" };
168
+ }
169
+ if (activity.activityScore < 45) {
170
+ return { verdict: "Slowing Down", emoji: "\u{26A0}\u{FE0F}" };
171
+ }
172
+ if (busFactor.busFactor <= 1 && busFactor.totalContributors > 1) {
173
+ return { verdict: "Active but Understaffed", emoji: "\u{1F9D1}\u200D\u{1F4BB}" };
174
+ }
175
+ return { verdict: "Active & Healthy", emoji: "\u{1F49A}" };
176
+ }
177
+ async function generatePulseReport(owner, repo) {
178
+ // Fetch repo info first (needed for branch, archived status, etc.)
179
+ const repoInfo = await (0, github_1.fetchRepo)(owner, repo);
180
+ // Run all analyses in parallel
181
+ const [activity, busFactorResult, health, dependencies] = await Promise.all([
182
+ analyzeActivity(owner, repo),
183
+ analyzeBusFactor(owner, repo),
184
+ analyzeHealth(owner, repo, repoInfo.has_issues),
185
+ analyzeDependencies(owner, repo, repoInfo.default_branch),
186
+ ]);
187
+ const { verdict, emoji } = computeVerdict(repoInfo, activity, busFactorResult, health);
188
+ return {
189
+ repo: repoInfo,
190
+ activity,
191
+ busFactor: busFactorResult,
192
+ health,
193
+ dependencies,
194
+ verdict,
195
+ verdictEmoji: emoji,
196
+ };
197
+ }
198
+ //# sourceMappingURL=analysis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analysis.js","sourceRoot":"","sources":["../src/analysis.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { PulseReport } from "./analysis";
2
+ export declare function displayReport(report: PulseReport): void;
3
+ export declare function displayCompact(report: PulseReport): void;
4
+ //# sourceMappingURL=display.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"display.d.ts","sourceRoot":"","sources":["../src/display.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAkBzC,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAkJvD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAKxD"}
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.displayReport = displayReport;
7
+ exports.displayCompact = displayCompact;
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ function bar(value, max, width = 20) {
10
+ const filled = Math.round((value / max) * width);
11
+ const empty = width - filled;
12
+ const color = value / max > 0.7 ? chalk_1.default.green : value / max > 0.4 ? chalk_1.default.yellow : chalk_1.default.red;
13
+ return color("\u2588".repeat(filled)) + chalk_1.default.gray("\u2591".repeat(empty));
14
+ }
15
+ function formatHours(hours) {
16
+ if (hours === null)
17
+ return chalk_1.default.gray("N/A");
18
+ if (hours < 1)
19
+ return chalk_1.default.green(`${Math.round(hours * 60)}m`);
20
+ if (hours < 24)
21
+ return chalk_1.default.green(`${Math.round(hours)}h`);
22
+ if (hours < 72)
23
+ return chalk_1.default.yellow(`${Math.round(hours / 24)}d`);
24
+ return chalk_1.default.red(`${Math.round(hours / 24)}d`);
25
+ }
26
+ function displayReport(report) {
27
+ const { repo, activity, busFactor, health, dependencies, verdict, verdictEmoji } = report;
28
+ const line = chalk_1.default.gray("\u2500".repeat(56));
29
+ console.log();
30
+ console.log(chalk_1.default.bold.white(` ${verdictEmoji} ${repo.full_name}`) +
31
+ chalk_1.default.gray(` \u2014 ${verdict}`));
32
+ console.log(line);
33
+ // Quick stats
34
+ console.log(chalk_1.default.gray(" \u2B50 ") +
35
+ chalk_1.default.white(repo.stargazers_count.toLocaleString()) +
36
+ chalk_1.default.gray(" \u{1F534} ") +
37
+ chalk_1.default.white(repo.forks_count.toLocaleString()) +
38
+ chalk_1.default.gray(" \u{1F441} ") +
39
+ chalk_1.default.white((repo.subscribers_count || 0).toLocaleString()) +
40
+ chalk_1.default.gray(" \u{1F4CB} ") +
41
+ chalk_1.default.white(repo.open_issues_count.toLocaleString() + " open issues"));
42
+ if (repo.description) {
43
+ console.log(chalk_1.default.gray(" ") + chalk_1.default.italic(repo.description));
44
+ }
45
+ console.log();
46
+ // Activity
47
+ console.log(chalk_1.default.bold.cyan(" ACTIVITY (last 30 days)"));
48
+ console.log(chalk_1.default.gray(" Score: ") +
49
+ bar(activity.activityScore, 100) +
50
+ chalk_1.default.white(` ${activity.activityScore}/100`));
51
+ console.log(chalk_1.default.gray(" Commits: ") +
52
+ chalk_1.default.white(`${activity.commits30d}`) +
53
+ chalk_1.default.gray(` (${activity.commits7d} in last 7d)`));
54
+ console.log(chalk_1.default.gray(" PRs opened: ") + chalk_1.default.white(`${activity.prsOpened30d}`));
55
+ console.log(chalk_1.default.gray(" PRs merged: ") + chalk_1.default.white(`${activity.prsMerged30d}`));
56
+ console.log(chalk_1.default.gray(" Issues opened: ") + chalk_1.default.white(`${activity.issuesOpened30d}`));
57
+ console.log(chalk_1.default.gray(" Issues closed: ") + chalk_1.default.white(`${activity.issuesClosed30d}`));
58
+ console.log();
59
+ // Bus Factor
60
+ console.log(chalk_1.default.bold.cyan(" BUS FACTOR"));
61
+ const bfColor = busFactor.busFactor >= 5
62
+ ? chalk_1.default.green
63
+ : busFactor.busFactor >= 3
64
+ ? chalk_1.default.yellow
65
+ : chalk_1.default.red;
66
+ console.log(chalk_1.default.gray(" Bus factor: ") +
67
+ bfColor(`${busFactor.busFactor}`) +
68
+ chalk_1.default.gray(` (${busFactor.totalContributors} total contributors)`));
69
+ if (busFactor.busFactor <= 2) {
70
+ console.log(chalk_1.default.gray(" ") +
71
+ chalk_1.default.red("\u26A0 High risk: very few people do most of the work"));
72
+ }
73
+ if (busFactor.topContributors.length > 0) {
74
+ console.log(chalk_1.default.gray(" Top contributors (80% of commits):"));
75
+ for (const c of busFactor.topContributors) {
76
+ console.log(chalk_1.default.gray(" \u2022 ") + chalk_1.default.white(`@${c.login}`) + chalk_1.default.gray(` ${c.percentage}%`));
77
+ }
78
+ }
79
+ console.log();
80
+ // Health
81
+ console.log(chalk_1.default.bold.cyan(" HEALTH METRICS"));
82
+ console.log(chalk_1.default.gray(" First response: ") +
83
+ formatHours(health.medianFirstResponseHours) +
84
+ chalk_1.default.gray(" (median estimate)"));
85
+ console.log(chalk_1.default.gray(" PR merge time: ") +
86
+ formatHours(health.medianPRMergeHours) +
87
+ chalk_1.default.gray(" (median)"));
88
+ console.log(chalk_1.default.gray(" Issue close %: ") +
89
+ (health.issueCloseRate >= 60
90
+ ? chalk_1.default.green(`${health.issueCloseRate}%`)
91
+ : health.issueCloseRate >= 30
92
+ ? chalk_1.default.yellow(`${health.issueCloseRate}%`)
93
+ : chalk_1.default.red(`${health.issueCloseRate}%`)));
94
+ if (!health.hasIssuesEnabled) {
95
+ console.log(chalk_1.default.gray(" ") + chalk_1.default.yellow("Issues are disabled on this repo"));
96
+ }
97
+ console.log();
98
+ // Dependencies
99
+ console.log(chalk_1.default.bold.cyan(" DEPENDENCIES"));
100
+ console.log(chalk_1.default.gray(" ") + chalk_1.default.white(dependencies.note));
101
+ console.log();
102
+ // Last push
103
+ const daysSinceLastPush = Math.round((Date.now() - new Date(repo.pushed_at).getTime()) / (1000 * 60 * 60 * 24));
104
+ console.log(chalk_1.default.gray(" Last push: ") +
105
+ (daysSinceLastPush < 7
106
+ ? chalk_1.default.green(`${daysSinceLastPush}d ago`)
107
+ : daysSinceLastPush < 30
108
+ ? chalk_1.default.yellow(`${daysSinceLastPush}d ago`)
109
+ : chalk_1.default.red(`${daysSinceLastPush}d ago`)));
110
+ // License
111
+ if (repo.license) {
112
+ console.log(chalk_1.default.gray(" License: ") + chalk_1.default.white(repo.license.spdx_id));
113
+ }
114
+ console.log(line);
115
+ console.log(chalk_1.default.bold(` VERDICT: ${verdictEmoji} ${verdict}`));
116
+ console.log(line);
117
+ console.log();
118
+ // Token hint
119
+ if (!process.env.GITHUB_TOKEN && !process.env.GH_TOKEN) {
120
+ console.log(chalk_1.default.gray(" Tip: Set GITHUB_TOKEN env var for higher API rate limits (60/hr -> 5000/hr)"));
121
+ console.log();
122
+ }
123
+ }
124
+ function displayCompact(report) {
125
+ const { repo, activity, busFactor, verdict, verdictEmoji } = report;
126
+ console.log(`${verdictEmoji} ${repo.full_name}: ${verdict} | Activity: ${activity.activityScore}/100 | Bus factor: ${busFactor.busFactor} | Stars: ${repo.stargazers_count}`);
127
+ }
128
+ //# sourceMappingURL=display.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"display.js","sourceRoot":"","sources":["../src/display.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ export interface GitHubRepo {
2
+ full_name: string;
3
+ name: string;
4
+ owner: {
5
+ login: string;
6
+ };
7
+ description: string | null;
8
+ stargazers_count: number;
9
+ forks_count: number;
10
+ open_issues_count: number;
11
+ archived: boolean;
12
+ disabled: boolean;
13
+ pushed_at: string;
14
+ created_at: string;
15
+ updated_at: string;
16
+ default_branch: string;
17
+ license: {
18
+ spdx_id: string;
19
+ } | null;
20
+ topics: string[];
21
+ subscribers_count: number;
22
+ has_issues: boolean;
23
+ }
24
+ export interface GitHubCommit {
25
+ sha: string;
26
+ commit: {
27
+ author: {
28
+ name: string;
29
+ date: string;
30
+ };
31
+ message: string;
32
+ };
33
+ author: {
34
+ login: string;
35
+ } | null;
36
+ }
37
+ export interface GitHubIssue {
38
+ number: number;
39
+ state: string;
40
+ pull_request?: unknown;
41
+ created_at: string;
42
+ closed_at: string | null;
43
+ comments: number;
44
+ user: {
45
+ login: string;
46
+ } | null;
47
+ }
48
+ export interface GitHubPR {
49
+ number: number;
50
+ state: string;
51
+ created_at: string;
52
+ closed_at: string | null;
53
+ merged_at: string | null;
54
+ user: {
55
+ login: string;
56
+ } | null;
57
+ }
58
+ export interface PackageJson {
59
+ dependencies?: Record<string, string>;
60
+ devDependencies?: Record<string, string>;
61
+ }
62
+ export declare function fetchRepo(owner: string, repo: string): Promise<GitHubRepo>;
63
+ export declare function fetchCommits(owner: string, repo: string, since: string, perPage?: number): Promise<GitHubCommit[]>;
64
+ export declare function fetchIssues(owner: string, repo: string, state: string, since: string, perPage?: number): Promise<GitHubIssue[]>;
65
+ export declare function fetchPRs(owner: string, repo: string, state: string, perPage?: number): Promise<GitHubPR[]>;
66
+ export declare function fetchPackageJson(owner: string, repo: string, branch: string): Promise<PackageJson | null>;
67
+ export declare function fetchContributors(owner: string, repo: string, perPage?: number): Promise<Array<{
68
+ login: string;
69
+ contributions: number;
70
+ }>>;
71
+ //# sourceMappingURL=github.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../src/github.ts"],"names":[],"mappings":"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"}
package/dist/github.js ADDED
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.fetchRepo = fetchRepo;
7
+ exports.fetchCommits = fetchCommits;
8
+ exports.fetchIssues = fetchIssues;
9
+ exports.fetchPRs = fetchPRs;
10
+ exports.fetchPackageJson = fetchPackageJson;
11
+ exports.fetchContributors = fetchContributors;
12
+ const https_1 = __importDefault(require("https"));
13
+ function githubFetch(path) {
14
+ return new Promise((resolve, reject) => {
15
+ const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
16
+ const headers = {
17
+ "User-Agent": "gitpulse-cli/1.0",
18
+ Accept: "application/vnd.github.v3+json",
19
+ };
20
+ if (token) {
21
+ headers["Authorization"] = `token ${token}`;
22
+ }
23
+ const options = {
24
+ hostname: "api.github.com",
25
+ path,
26
+ method: "GET",
27
+ headers,
28
+ };
29
+ const req = https_1.default.request(options, (res) => {
30
+ let data = "";
31
+ res.on("data", (chunk) => {
32
+ data += chunk.toString();
33
+ });
34
+ res.on("end", () => {
35
+ if (res.statusCode === 403 && data.includes("rate limit")) {
36
+ reject(new Error("GitHub API rate limit exceeded. Set GITHUB_TOKEN env var for higher limits."));
37
+ return;
38
+ }
39
+ if (res.statusCode === 404) {
40
+ reject(new Error("Repository not found. Check the owner/repo format."));
41
+ return;
42
+ }
43
+ if (res.statusCode && res.statusCode >= 400) {
44
+ reject(new Error(`GitHub API error ${res.statusCode}: ${data.slice(0, 200)}`));
45
+ return;
46
+ }
47
+ try {
48
+ resolve(JSON.parse(data));
49
+ }
50
+ catch {
51
+ reject(new Error("Failed to parse GitHub API response"));
52
+ }
53
+ });
54
+ });
55
+ req.on("error", reject);
56
+ req.setTimeout(15000, () => {
57
+ req.destroy();
58
+ reject(new Error("Request timed out"));
59
+ });
60
+ req.end();
61
+ });
62
+ }
63
+ function rawContentFetch(owner, repo, path, branch) {
64
+ return new Promise((resolve, reject) => {
65
+ const url = `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/${path}`;
66
+ https_1.default
67
+ .get(url, { headers: { "User-Agent": "gitpulse-cli/1.0" } }, (res) => {
68
+ if (res.statusCode === 404) {
69
+ resolve("");
70
+ return;
71
+ }
72
+ let data = "";
73
+ res.on("data", (chunk) => {
74
+ data += chunk.toString();
75
+ });
76
+ res.on("end", () => resolve(data));
77
+ })
78
+ .on("error", () => resolve(""));
79
+ });
80
+ }
81
+ async function fetchRepo(owner, repo) {
82
+ return githubFetch(`/repos/${owner}/${repo}`);
83
+ }
84
+ async function fetchCommits(owner, repo, since, perPage = 100) {
85
+ return githubFetch(`/repos/${owner}/${repo}/commits?since=${since}&per_page=${perPage}`);
86
+ }
87
+ async function fetchIssues(owner, repo, state, since, perPage = 100) {
88
+ return githubFetch(`/repos/${owner}/${repo}/issues?state=${state}&since=${since}&per_page=${perPage}&sort=updated`);
89
+ }
90
+ async function fetchPRs(owner, repo, state, perPage = 100) {
91
+ return githubFetch(`/repos/${owner}/${repo}/pulls?state=${state}&sort=updated&direction=desc&per_page=${perPage}`);
92
+ }
93
+ async function fetchPackageJson(owner, repo, branch) {
94
+ const raw = await rawContentFetch(owner, repo, "package.json", branch);
95
+ if (!raw)
96
+ return null;
97
+ try {
98
+ return JSON.parse(raw);
99
+ }
100
+ catch {
101
+ return null;
102
+ }
103
+ }
104
+ async function fetchContributors(owner, repo, perPage = 100) {
105
+ return githubFetch(`/repos/${owner}/${repo}/contributors?per_page=${perPage}`);
106
+ }
107
+ //# sourceMappingURL=github.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.js","sourceRoot":"","sources":["../src/github.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const commander_1 = require("commander");
8
+ const ora_1 = __importDefault(require("ora"));
9
+ const chalk_1 = __importDefault(require("chalk"));
10
+ const analysis_1 = require("./analysis");
11
+ const display_1 = require("./display");
12
+ const program = new commander_1.Command();
13
+ program
14
+ .name("gitpulse")
15
+ .description("Instant health check for any GitHub repo. Get activity scores, bus factor, health metrics, and a verdict.")
16
+ .version("1.0.0")
17
+ .argument("<repo>", 'GitHub repo in "owner/repo" format (e.g., facebook/react)')
18
+ .option("--compact", "Show one-line compact output")
19
+ .option("--json", "Output raw JSON data")
20
+ .action(async (repoArg, options) => {
21
+ // Parse owner/repo
22
+ const parts = repoArg.replace(/^https?:\/\/github\.com\//, "").replace(/\/$/, "").split("/");
23
+ if (parts.length !== 2 || !parts[0] || !parts[1]) {
24
+ console.error(chalk_1.default.red('Error: Please provide a repo in "owner/repo" format.'));
25
+ console.error(chalk_1.default.gray(" Example: gitpulse facebook/react"));
26
+ process.exit(1);
27
+ }
28
+ const [owner, repo] = parts;
29
+ const spinner = (0, ora_1.default)({
30
+ text: `Analyzing ${owner}/${repo}...`,
31
+ color: "cyan",
32
+ }).start();
33
+ try {
34
+ const report = await (0, analysis_1.generatePulseReport)(owner, repo);
35
+ spinner.stop();
36
+ if (options.json) {
37
+ console.log(JSON.stringify(report, null, 2));
38
+ }
39
+ else if (options.compact) {
40
+ (0, display_1.displayCompact)(report);
41
+ }
42
+ else {
43
+ (0, display_1.displayReport)(report);
44
+ }
45
+ }
46
+ catch (err) {
47
+ spinner.fail(chalk_1.default.red("Analysis failed"));
48
+ if (err instanceof Error) {
49
+ console.error(chalk_1.default.red(` ${err.message}`));
50
+ }
51
+ if (err instanceof Error &&
52
+ err.message.includes("rate limit")) {
53
+ console.error(chalk_1.default.yellow("\n Set GITHUB_TOKEN or GH_TOKEN environment variable for 5000 requests/hr."));
54
+ }
55
+ process.exit(1);
56
+ }
57
+ });
58
+ program.parse();
59
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AAEA,yCAAoC;AACpC,8CAAsB;AACtB,kDAA0B;AAC1B,yCAAiD;AACjD,uCAA0D;AAE1D,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CACV,2GAA2G,CAC5G;KACA,OAAO,CAAC,OAAO,CAAC;KAChB,QAAQ,CAAC,QAAQ,EAAE,2DAA2D,CAAC;KAC/E,MAAM,CAAC,WAAW,EAAE,8BAA8B,CAAC;KACnD,MAAM,CAAC,QAAQ,EAAE,sBAAsB,CAAC;KACxC,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,OAA8C,EAAE,EAAE;IAChF,mBAAmB;IACnB,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,2BAA2B,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7F,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,OAAO,CAAC,KAAK,CACX,eAAK,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAClE,CAAC;QACF,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC,CAAC;QAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC;IAC5B,MAAM,OAAO,GAAG,IAAA,aAAG,EAAC;QAClB,IAAI,EAAE,aAAa,KAAK,IAAI,IAAI,KAAK;QACrC,KAAK,EAAE,MAAM;KACd,CAAC,CAAC,KAAK,EAAE,CAAC;IAEX,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAA,8BAAmB,EAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACtD,OAAO,CAAC,IAAI,EAAE,CAAC;QAEf,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC/C,CAAC;aAAM,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YAC3B,IAAA,wBAAc,EAAC,MAAM,CAAC,CAAC;QACzB,CAAC;aAAM,CAAC;YACN,IAAA,uBAAa,EAAC,MAAM,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,OAAO,CAAC,IAAI,CAAC,eAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC;QAC3C,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;YACzB,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAC/C,CAAC;QACD,IACE,GAAG,YAAY,KAAK;YACpB,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,EAClC,CAAC;YACD,OAAO,CAAC,KAAK,CACX,eAAK,CAAC,MAAM,CACV,6EAA6E,CAC9E,CACF,CAAC;QACJ,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@chengyixu/gitpulse",
3
+ "version": "1.0.0",
4
+ "description": "Instant health check for any GitHub repo. Activity score, bus factor, response times, dependency freshness, and a one-line verdict.",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "gitpulse": "dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "start": "node dist/index.js",
12
+ "dev": "ts-node src/index.ts"
13
+ },
14
+ "keywords": [
15
+ "github",
16
+ "repo",
17
+ "health",
18
+ "activity",
19
+ "bus-factor",
20
+ "dependencies",
21
+ "cli",
22
+ "analysis",
23
+ "open-source",
24
+ "maintenance",
25
+ "pulse",
26
+ "metrics"
27
+ ],
28
+ "author": "wilsonxu",
29
+ "license": "MIT",
30
+ "dependencies": {
31
+ "chalk": "^4.1.2",
32
+ "commander": "^12.1.0",
33
+ "ora": "^5.4.1"
34
+ },
35
+ "devDependencies": {
36
+ "@types/node": "^20.14.0",
37
+ "typescript": "^5.5.0"
38
+ },
39
+ "files": [
40
+ "dist/**/*"
41
+ ],
42
+ "engines": {
43
+ "node": ">=18.0.0"
44
+ },
45
+ "repository": {
46
+ "type": "git",
47
+ "url": "https://github.com/chengyixu/gitpulse"
48
+ }
49
+ }