@gitgate/gg-cli 0.1.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/dist/commands/actions.d.ts +11 -0
- package/dist/commands/actions.d.ts.map +1 -0
- package/dist/commands/actions.js +97 -0
- package/dist/commands/actions.js.map +1 -0
- package/dist/commands/auth.d.ts +11 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +104 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/import.d.ts +10 -0
- package/dist/commands/import.d.ts.map +1 -0
- package/dist/commands/import.js +101 -0
- package/dist/commands/import.js.map +1 -0
- package/dist/commands/issue.d.ts +12 -0
- package/dist/commands/issue.d.ts.map +1 -0
- package/dist/commands/issue.js +140 -0
- package/dist/commands/issue.js.map +1 -0
- package/dist/commands/pr.d.ts +14 -0
- package/dist/commands/pr.d.ts.map +1 -0
- package/dist/commands/pr.js +150 -0
- package/dist/commands/pr.js.map +1 -0
- package/dist/commands/repo.d.ts +19 -0
- package/dist/commands/repo.d.ts.map +1 -0
- package/dist/commands/repo.js +199 -0
- package/dist/commands/repo.js.map +1 -0
- package/dist/commands/search.d.ts +6 -0
- package/dist/commands/search.d.ts.map +1 -0
- package/dist/commands/search.js +46 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/viz.d.ts +13 -0
- package/dist/commands/viz.d.ts.map +1 -0
- package/dist/commands/viz.js +167 -0
- package/dist/commands/viz.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api-client.d.ts +23 -0
- package/dist/lib/api-client.d.ts.map +1 -0
- package/dist/lib/api-client.js +79 -0
- package/dist/lib/api-client.js.map +1 -0
- package/dist/lib/config.d.ts +16 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +44 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/output.d.ts +8 -0
- package/dist/lib/output.d.ts.map +1 -0
- package/dist/lib/output.js +46 -0
- package/dist/lib/output.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gg pr — pull request management commands.
|
|
3
|
+
*
|
|
4
|
+
* gg pr create <owner/repo> — Create a pull request
|
|
5
|
+
* gg pr list <owner/repo> — List pull requests
|
|
6
|
+
* gg pr view <owner/repo> <num> — View PR details
|
|
7
|
+
* gg pr merge <owner/repo> <num> — Merge a pull request
|
|
8
|
+
* gg pr close <owner/repo> <num> — Close a pull request
|
|
9
|
+
* gg pr review <owner/repo> <num> — Submit a review
|
|
10
|
+
* gg pr diff <owner/repo> <num> — View PR diff
|
|
11
|
+
*/
|
|
12
|
+
import { Command } from 'commander';
|
|
13
|
+
import { isAuthenticated } from '../lib/config';
|
|
14
|
+
import { getClient } from '../lib/api-client';
|
|
15
|
+
import { table, relativeTime, statusIcon, truncate } from '../lib/output';
|
|
16
|
+
export const prCommand = new Command('pr')
|
|
17
|
+
.description('Manage pull requests');
|
|
18
|
+
prCommand
|
|
19
|
+
.command('create')
|
|
20
|
+
.description('Create a pull request')
|
|
21
|
+
.argument('<repo>', 'owner/repo')
|
|
22
|
+
.option('-t, --title <title>', 'PR title')
|
|
23
|
+
.option('-b, --body <body>', 'PR body')
|
|
24
|
+
.option('--head <ref>', 'Head branch')
|
|
25
|
+
.option('--base <ref>', 'Base branch', 'main')
|
|
26
|
+
.option('--draft', 'Create as draft')
|
|
27
|
+
.action(async (repoArg, opts) => {
|
|
28
|
+
requireAuth();
|
|
29
|
+
const [owner, repo] = parseRepo(repoArg);
|
|
30
|
+
if (!opts.title || !opts.head) {
|
|
31
|
+
console.error('Title and head branch are required.');
|
|
32
|
+
console.error('Usage: gg pr create owner/repo -t "title" --head feature-branch');
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
const client = getClient();
|
|
36
|
+
const res = await client.post(`/api/repos/${owner}/${repo}/pulls`, {
|
|
37
|
+
title: opts.title,
|
|
38
|
+
body: opts.body ?? '',
|
|
39
|
+
headRef: opts.head,
|
|
40
|
+
baseRef: opts.base,
|
|
41
|
+
isDraft: opts.draft ?? false,
|
|
42
|
+
});
|
|
43
|
+
console.log(`Created PR #${res.data.number}: ${res.data.title}`);
|
|
44
|
+
});
|
|
45
|
+
prCommand
|
|
46
|
+
.command('list')
|
|
47
|
+
.description('List pull requests')
|
|
48
|
+
.alias('ls')
|
|
49
|
+
.argument('<repo>', 'owner/repo')
|
|
50
|
+
.option('-s, --state <state>', 'Filter by state (open/closed/merged/all)', 'open')
|
|
51
|
+
.action(async (repoArg, opts) => {
|
|
52
|
+
const [owner, repo] = parseRepo(repoArg);
|
|
53
|
+
const client = getClient();
|
|
54
|
+
const res = await client.get(`/api/repos/${owner}/${repo}/pulls?state=${opts.state}`);
|
|
55
|
+
if (res.data.length === 0) {
|
|
56
|
+
console.log(`No ${opts.state} pull requests in ${owner}/${repo}`);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const rows = res.data.map((pr) => [
|
|
60
|
+
statusIcon(pr.state),
|
|
61
|
+
`#${pr.number}`,
|
|
62
|
+
truncate(pr.title, 50),
|
|
63
|
+
`${pr.headRef} -> ${pr.baseRef}`,
|
|
64
|
+
`+${pr.additions} -${pr.deletions}`,
|
|
65
|
+
relativeTime(pr.createdAt),
|
|
66
|
+
]);
|
|
67
|
+
console.log(table(['', '#', 'TITLE', 'BRANCHES', 'CHANGES', 'CREATED'], rows));
|
|
68
|
+
});
|
|
69
|
+
prCommand
|
|
70
|
+
.command('view')
|
|
71
|
+
.description('View pull request details')
|
|
72
|
+
.argument('<repo>', 'owner/repo')
|
|
73
|
+
.argument('<number>', 'PR number')
|
|
74
|
+
.action(async (repoArg, number) => {
|
|
75
|
+
const [owner, repo] = parseRepo(repoArg);
|
|
76
|
+
const client = getClient();
|
|
77
|
+
const res = await client.get(`/api/repos/${owner}/${repo}/pulls/${number}`);
|
|
78
|
+
const pr = res.data;
|
|
79
|
+
console.log(`#${pr.number} ${pr.title}`);
|
|
80
|
+
console.log(`State: ${pr.state}${pr.isDraft ? ' (draft)' : ''}`);
|
|
81
|
+
console.log(`${pr.headRef} -> ${pr.baseRef}`);
|
|
82
|
+
console.log(`+${pr.additions} -${pr.deletions} across ${pr.changedFiles} files`);
|
|
83
|
+
console.log(`Created: ${relativeTime(pr.createdAt)}`);
|
|
84
|
+
if (pr.mergedAt)
|
|
85
|
+
console.log(`Merged: ${relativeTime(pr.mergedAt)}`);
|
|
86
|
+
if (pr.body) {
|
|
87
|
+
console.log('');
|
|
88
|
+
console.log(pr.body);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
prCommand
|
|
92
|
+
.command('merge')
|
|
93
|
+
.description('Merge a pull request')
|
|
94
|
+
.argument('<repo>', 'owner/repo')
|
|
95
|
+
.argument('<number>', 'PR number')
|
|
96
|
+
.option('-s, --strategy <strategy>', 'Merge strategy (merge/squash/rebase)', 'merge')
|
|
97
|
+
.action(async (repoArg, number, opts) => {
|
|
98
|
+
requireAuth();
|
|
99
|
+
const [owner, repo] = parseRepo(repoArg);
|
|
100
|
+
const client = getClient();
|
|
101
|
+
const res = await client.post(`/api/repos/${owner}/${repo}/pulls/${number}/merge`, { strategy: opts.strategy });
|
|
102
|
+
console.log(`PR #${number} merged (${opts.strategy}). SHA: ${res.data.sha.substring(0, 7)}`);
|
|
103
|
+
});
|
|
104
|
+
prCommand
|
|
105
|
+
.command('close')
|
|
106
|
+
.description('Close a pull request')
|
|
107
|
+
.argument('<repo>', 'owner/repo')
|
|
108
|
+
.argument('<number>', 'PR number')
|
|
109
|
+
.action(async (repoArg, number) => {
|
|
110
|
+
requireAuth();
|
|
111
|
+
const [owner, repo] = parseRepo(repoArg);
|
|
112
|
+
const client = getClient();
|
|
113
|
+
await client.patch(`/api/repos/${owner}/${repo}/pulls/${number}`, { state: 'closed' });
|
|
114
|
+
console.log(`PR #${number} closed.`);
|
|
115
|
+
});
|
|
116
|
+
prCommand
|
|
117
|
+
.command('review')
|
|
118
|
+
.description('Submit a review')
|
|
119
|
+
.argument('<repo>', 'owner/repo')
|
|
120
|
+
.argument('<number>', 'PR number')
|
|
121
|
+
.option('-a, --approve', 'Approve the PR')
|
|
122
|
+
.option('-r, --request-changes', 'Request changes')
|
|
123
|
+
.option('-c, --comment', 'Comment only')
|
|
124
|
+
.option('-b, --body <body>', 'Review body')
|
|
125
|
+
.action(async (repoArg, number, opts) => {
|
|
126
|
+
requireAuth();
|
|
127
|
+
const [owner, repo] = parseRepo(repoArg);
|
|
128
|
+
const state = opts.approve ? 'approved' : opts.requestChanges ? 'changes_requested' : 'commented';
|
|
129
|
+
const client = getClient();
|
|
130
|
+
await client.post(`/api/repos/${owner}/${repo}/pulls/${number}/reviews`, {
|
|
131
|
+
state,
|
|
132
|
+
body: opts.body ?? '',
|
|
133
|
+
});
|
|
134
|
+
console.log(`Review submitted: ${state}`);
|
|
135
|
+
});
|
|
136
|
+
function parseRepo(arg) {
|
|
137
|
+
const parts = arg.split('/');
|
|
138
|
+
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
139
|
+
console.error('Invalid repo format. Use: owner/repo');
|
|
140
|
+
process.exit(1);
|
|
141
|
+
}
|
|
142
|
+
return [parts[0], parts[1]];
|
|
143
|
+
}
|
|
144
|
+
function requireAuth() {
|
|
145
|
+
if (!isAuthenticated()) {
|
|
146
|
+
console.error('Not authenticated. Run: gg auth login');
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=pr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr.js","sourceRoot":"","sources":["../../src/commands/pr.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE1E,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;KACvC,WAAW,CAAC,sBAAsB,CAAC,CAAC;AAEvC,SAAS;KACN,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,uBAAuB,CAAC;KACpC,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;KAChC,MAAM,CAAC,qBAAqB,EAAE,UAAU,CAAC;KACzC,MAAM,CAAC,mBAAmB,EAAE,SAAS,CAAC;KACtC,MAAM,CAAC,cAAc,EAAE,aAAa,CAAC;KACrC,MAAM,CAAC,cAAc,EAAE,aAAa,EAAE,MAAM,CAAC;KAC7C,MAAM,CAAC,SAAS,EAAE,iBAAiB,CAAC;KACpC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;IAC9B,WAAW,EAAE,CAAC;IACd,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IAEzC,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC9B,OAAO,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;QACrD,OAAO,CAAC,KAAK,CAAC,iEAAiE,CAAC,CAAC;QACjF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAC3B,cAAc,KAAK,IAAI,IAAI,QAAQ,EACnC;QACE,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE;QACrB,OAAO,EAAE,IAAI,CAAC,IAAI;QAClB,OAAO,EAAE,IAAI,CAAC,IAAI;QAClB,OAAO,EAAE,IAAI,CAAC,KAAK,IAAI,KAAK;KAC7B,CACF,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,eAAe,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;AACnE,CAAC,CAAC,CAAC;AAEL,SAAS;KACN,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,oBAAoB,CAAC;KACjC,KAAK,CAAC,IAAI,CAAC;KACX,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;KAChC,MAAM,CAAC,qBAAqB,EAAE,0CAA0C,EAAE,MAAM,CAAC;KACjF,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;IAC9B,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,GAAG,CAGtB,cAAc,KAAK,IAAI,IAAI,gBAAgB,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IAE/D,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,KAAK,qBAAqB,KAAK,IAAI,IAAI,EAAE,CAAC,CAAC;QAClE,OAAO;IACT,CAAC;IAED,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC;QAChC,UAAU,CAAC,EAAE,CAAC,KAAK,CAAC;QACpB,IAAI,EAAE,CAAC,MAAM,EAAE;QACf,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC;QACtB,GAAG,EAAE,CAAC,OAAO,OAAO,EAAE,CAAC,OAAO,EAAE;QAChC,IAAI,EAAE,CAAC,SAAS,KAAK,EAAE,CAAC,SAAS,EAAE;QACnC,YAAY,CAAC,EAAE,CAAC,SAAS,CAAC;KAC3B,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AACjF,CAAC,CAAC,CAAC;AAEL,SAAS;KACN,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,2BAA2B,CAAC;KACxC,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;KAChC,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC;KACjC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE;IAChC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,GAAG,CAKvB,cAAc,KAAK,IAAI,IAAI,UAAU,MAAM,EAAE,CAAC,CAAC;IAEpD,MAAM,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC;IACpB,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,KAAK,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACjE,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,OAAO,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,SAAS,KAAK,EAAE,CAAC,SAAS,WAAW,EAAE,CAAC,YAAY,QAAQ,CAAC,CAAC;IACjF,OAAO,CAAC,GAAG,CAAC,YAAY,YAAY,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACtD,IAAI,EAAE,CAAC,QAAQ;QAAE,OAAO,CAAC,GAAG,CAAC,WAAW,YAAY,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACrE,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IACvB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,SAAS;KACN,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,sBAAsB,CAAC;KACnC,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;KAChC,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC;KACjC,MAAM,CAAC,2BAA2B,EAAE,sCAAsC,EAAE,OAAO,CAAC;KACpF,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;IACtC,WAAW,EAAE,CAAC;IACd,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAC3B,cAAc,KAAK,IAAI,IAAI,UAAU,MAAM,QAAQ,EACnD,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAC5B,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,OAAO,MAAM,YAAY,IAAI,CAAC,QAAQ,WAAW,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AAC/F,CAAC,CAAC,CAAC;AAEL,SAAS;KACN,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,sBAAsB,CAAC;KACnC,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;KAChC,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC;KACjC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE;IAChC,WAAW,EAAE,CAAC;IACd,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,MAAM,CAAC,KAAK,CAAC,cAAc,KAAK,IAAI,IAAI,UAAU,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IACvF,OAAO,CAAC,GAAG,CAAC,OAAO,MAAM,UAAU,CAAC,CAAC;AACvC,CAAC,CAAC,CAAC;AAEL,SAAS;KACN,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,iBAAiB,CAAC;KAC9B,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;KAChC,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC;KACjC,MAAM,CAAC,eAAe,EAAE,gBAAgB,CAAC;KACzC,MAAM,CAAC,uBAAuB,EAAE,iBAAiB,CAAC;KAClD,MAAM,CAAC,eAAe,EAAE,cAAc,CAAC;KACvC,MAAM,CAAC,mBAAmB,EAAE,aAAa,CAAC;KAC1C,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;IACtC,WAAW,EAAE,CAAC;IACd,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,WAAW,CAAC;IAClG,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,MAAM,CAAC,IAAI,CAAC,cAAc,KAAK,IAAI,IAAI,UAAU,MAAM,UAAU,EAAE;QACvE,KAAK;QACL,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE;KACtB,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,CAAC,qBAAqB,KAAK,EAAE,CAAC,CAAC;AAC5C,CAAC,CAAC,CAAC;AAEL,SAAS,SAAS,CAAC,GAAW;IAC5B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;QACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,WAAW;IAClB,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;QACvB,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;QACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gg repo — repository management commands.
|
|
3
|
+
*
|
|
4
|
+
* Philosophy: git operations (clone, push, fetch) delegate to native git.
|
|
5
|
+
* Workflow operations (create, fork, star, delete) call the GitGate API.
|
|
6
|
+
* The CLI never reimplements git — it wraps it.
|
|
7
|
+
*
|
|
8
|
+
* gg repo create <name> — API: create repo, print clone URL
|
|
9
|
+
* gg repo list — API: list your repositories
|
|
10
|
+
* gg repo view <owner/repo> — API: repo details
|
|
11
|
+
* gg repo clone <owner/repo> — Native git: git clone <url>
|
|
12
|
+
* gg repo fork <owner/repo> — API: fork, then print clone URL
|
|
13
|
+
* gg repo delete <owner/repo> — API: archive repo
|
|
14
|
+
* gg repo set-remote [name] — Native git: set origin to GitGate URL
|
|
15
|
+
* gg repo push-all — Native git: push --all + push --tags
|
|
16
|
+
*/
|
|
17
|
+
import { Command } from 'commander';
|
|
18
|
+
export declare const repoCommand: Command;
|
|
19
|
+
//# sourceMappingURL=repo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo.d.ts","sourceRoot":"","sources":["../../src/commands/repo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,eAAO,MAAM,WAAW,SACa,CAAC"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gg repo — repository management commands.
|
|
3
|
+
*
|
|
4
|
+
* Philosophy: git operations (clone, push, fetch) delegate to native git.
|
|
5
|
+
* Workflow operations (create, fork, star, delete) call the GitGate API.
|
|
6
|
+
* The CLI never reimplements git — it wraps it.
|
|
7
|
+
*
|
|
8
|
+
* gg repo create <name> — API: create repo, print clone URL
|
|
9
|
+
* gg repo list — API: list your repositories
|
|
10
|
+
* gg repo view <owner/repo> — API: repo details
|
|
11
|
+
* gg repo clone <owner/repo> — Native git: git clone <url>
|
|
12
|
+
* gg repo fork <owner/repo> — API: fork, then print clone URL
|
|
13
|
+
* gg repo delete <owner/repo> — API: archive repo
|
|
14
|
+
* gg repo set-remote [name] — Native git: set origin to GitGate URL
|
|
15
|
+
* gg repo push-all — Native git: push --all + push --tags
|
|
16
|
+
*/
|
|
17
|
+
import { Command } from 'commander';
|
|
18
|
+
import { execSync } from 'node:child_process';
|
|
19
|
+
import { isAuthenticated, loadConfig } from '../lib/config';
|
|
20
|
+
import { getClient } from '../lib/api-client';
|
|
21
|
+
import { table, relativeTime } from '../lib/output';
|
|
22
|
+
export const repoCommand = new Command('repo')
|
|
23
|
+
.description('Manage repositories');
|
|
24
|
+
repoCommand
|
|
25
|
+
.command('create')
|
|
26
|
+
.description('Create a new repository')
|
|
27
|
+
.argument('<name>', 'Repository name')
|
|
28
|
+
.option('-d, --description <desc>', 'Repository description')
|
|
29
|
+
.option('--private', 'Make the repository private')
|
|
30
|
+
.option('--no-init', 'Do not initialize with a README')
|
|
31
|
+
.action(async (name, opts) => {
|
|
32
|
+
requireAuth();
|
|
33
|
+
const client = getClient();
|
|
34
|
+
const res = await client.post('/api/repos', {
|
|
35
|
+
name,
|
|
36
|
+
description: opts.description ?? '',
|
|
37
|
+
isPrivate: opts.private ?? false,
|
|
38
|
+
autoInit: opts.init !== false,
|
|
39
|
+
});
|
|
40
|
+
const config = loadConfig();
|
|
41
|
+
const webUrl = config.apiUrl.replace('api.', '');
|
|
42
|
+
console.log(`Repository created: ${res.data.name}`);
|
|
43
|
+
console.log(`Clone: git clone ${webUrl}/${loadConfig().username}/${name}.git`);
|
|
44
|
+
});
|
|
45
|
+
repoCommand
|
|
46
|
+
.command('list')
|
|
47
|
+
.description('List your repositories')
|
|
48
|
+
.alias('ls')
|
|
49
|
+
.action(async () => {
|
|
50
|
+
requireAuth();
|
|
51
|
+
const client = getClient();
|
|
52
|
+
const res = await client.get('/api/repos');
|
|
53
|
+
if (res.data.length === 0) {
|
|
54
|
+
console.log('No repositories found. Create one with: gg repo create <name>');
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const rows = res.data.map((r) => [
|
|
58
|
+
r.name,
|
|
59
|
+
r.isPrivate ? 'private' : 'public',
|
|
60
|
+
String(r.starCount),
|
|
61
|
+
r.description?.substring(0, 40) ?? '',
|
|
62
|
+
r.pushedAt ? relativeTime(r.pushedAt) : 'never',
|
|
63
|
+
]);
|
|
64
|
+
console.log(table(['NAME', 'VISIBILITY', 'STARS', 'DESCRIPTION', 'PUSHED'], rows));
|
|
65
|
+
});
|
|
66
|
+
repoCommand
|
|
67
|
+
.command('view')
|
|
68
|
+
.description('View repository details')
|
|
69
|
+
.argument('<repo>', 'owner/repo')
|
|
70
|
+
.action(async (repoArg) => {
|
|
71
|
+
const [owner, repo] = parseRepoArg(repoArg);
|
|
72
|
+
const client = getClient();
|
|
73
|
+
const res = await client.get(`/api/repos/${owner}/${repo}`);
|
|
74
|
+
const r = res.data;
|
|
75
|
+
console.log(`${owner}/${r.name}`);
|
|
76
|
+
console.log(r.description || '(no description)');
|
|
77
|
+
console.log('');
|
|
78
|
+
console.log(` Visibility: ${r.isPrivate ? 'Private' : 'Public'}`);
|
|
79
|
+
console.log(` Default: ${r.defaultBranch}`);
|
|
80
|
+
console.log(` Stars: ${r.starCount}`);
|
|
81
|
+
console.log(` Forks: ${r.forkCount}`);
|
|
82
|
+
console.log(` Issues: ${r.openIssueCount} open`);
|
|
83
|
+
console.log(` PRs: ${r.openPrCount} open`);
|
|
84
|
+
console.log(` Created: ${relativeTime(r.createdAt)}`);
|
|
85
|
+
});
|
|
86
|
+
repoCommand
|
|
87
|
+
.command('clone')
|
|
88
|
+
.description('Clone a repository')
|
|
89
|
+
.argument('<repo>', 'owner/repo')
|
|
90
|
+
.argument('[directory]', 'Target directory')
|
|
91
|
+
.action(async (repoArg, directory) => {
|
|
92
|
+
const [owner, repo] = parseRepoArg(repoArg);
|
|
93
|
+
const config = loadConfig();
|
|
94
|
+
const baseUrl = config.apiUrl.replace('/api', '').replace('api.', '');
|
|
95
|
+
const cloneUrl = `${baseUrl}/${owner}/${repo}.git`;
|
|
96
|
+
const dir = directory ?? repo;
|
|
97
|
+
console.log(`Cloning into '${dir}'...`);
|
|
98
|
+
try {
|
|
99
|
+
execSync(`git clone ${cloneUrl} ${dir}`, { stdio: 'inherit' });
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
console.error('Clone failed.');
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
repoCommand
|
|
107
|
+
.command('fork')
|
|
108
|
+
.description('Fork a repository')
|
|
109
|
+
.argument('<repo>', 'owner/repo')
|
|
110
|
+
.option('-n, --name <name>', 'Name for the fork')
|
|
111
|
+
.action(async (repoArg, opts) => {
|
|
112
|
+
requireAuth();
|
|
113
|
+
const [owner, repo] = parseRepoArg(repoArg);
|
|
114
|
+
const client = getClient();
|
|
115
|
+
const res = await client.post(`/api/repos/${owner}/${repo}/fork`, {
|
|
116
|
+
name: opts.name,
|
|
117
|
+
});
|
|
118
|
+
const config = loadConfig();
|
|
119
|
+
console.log(`Forked to ${config.username}/${res.data.name}`);
|
|
120
|
+
});
|
|
121
|
+
repoCommand
|
|
122
|
+
.command('delete')
|
|
123
|
+
.description('Delete a repository')
|
|
124
|
+
.argument('<repo>', 'owner/repo')
|
|
125
|
+
.option('-y, --yes', 'Skip confirmation')
|
|
126
|
+
.action(async (repoArg, opts) => {
|
|
127
|
+
requireAuth();
|
|
128
|
+
const [owner, repo] = parseRepoArg(repoArg);
|
|
129
|
+
if (!opts.yes) {
|
|
130
|
+
console.log(`This will archive ${owner}/${repo}. Use --yes to confirm.`);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const client = getClient();
|
|
134
|
+
await client.delete(`/api/repos/${owner}/${repo}`);
|
|
135
|
+
console.log(`Repository ${owner}/${repo} archived.`);
|
|
136
|
+
});
|
|
137
|
+
repoCommand
|
|
138
|
+
.command('set-remote')
|
|
139
|
+
.description('Set git origin to GitGate URL for current repo')
|
|
140
|
+
.argument('<repo>', 'owner/repo')
|
|
141
|
+
.argument('[remote]', 'Remote name', 'origin')
|
|
142
|
+
.action(async (repoArg, remote) => {
|
|
143
|
+
const [owner, repo] = parseRepoArg(repoArg);
|
|
144
|
+
const config = loadConfig();
|
|
145
|
+
const baseUrl = config.apiUrl.replace('api.', '');
|
|
146
|
+
const url = `${baseUrl}/${owner}/${repo}.git`;
|
|
147
|
+
try {
|
|
148
|
+
// Try set-url first (remote already exists)
|
|
149
|
+
execSync(`git remote set-url ${remote} ${url}`, { stdio: 'inherit' });
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
// Remote doesn't exist, add it
|
|
153
|
+
try {
|
|
154
|
+
execSync(`git remote add ${remote} ${url}`, { stdio: 'inherit' });
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
console.error(`Failed to set remote '${remote}'.`);
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
console.log(`Remote '${remote}' set to ${url}`);
|
|
162
|
+
});
|
|
163
|
+
repoCommand
|
|
164
|
+
.command('push-all')
|
|
165
|
+
.description('Push all branches and tags to origin (native git)')
|
|
166
|
+
.action(async () => {
|
|
167
|
+
console.log('Pushing all branches...');
|
|
168
|
+
try {
|
|
169
|
+
execSync('git push --all', { stdio: 'inherit' });
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
console.error('Failed to push branches.');
|
|
173
|
+
process.exit(1);
|
|
174
|
+
}
|
|
175
|
+
console.log('Pushing all tags...');
|
|
176
|
+
try {
|
|
177
|
+
execSync('git push --tags', { stdio: 'inherit' });
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
console.error('Failed to push tags.');
|
|
181
|
+
process.exit(1);
|
|
182
|
+
}
|
|
183
|
+
console.log('Done. All branches and tags pushed.');
|
|
184
|
+
});
|
|
185
|
+
function parseRepoArg(arg) {
|
|
186
|
+
const parts = arg.split('/');
|
|
187
|
+
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
188
|
+
console.error('Invalid repo format. Use: owner/repo');
|
|
189
|
+
process.exit(1);
|
|
190
|
+
}
|
|
191
|
+
return [parts[0], parts[1]];
|
|
192
|
+
}
|
|
193
|
+
function requireAuth() {
|
|
194
|
+
if (!isAuthenticated()) {
|
|
195
|
+
console.error('Not authenticated. Run: gg auth login');
|
|
196
|
+
process.exit(1);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=repo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo.js","sourceRoot":"","sources":["../../src/commands/repo.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,eAAO,MAAM,aAAa,SA0CtB,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gg search — search across code, repos, issues, PRs.
|
|
3
|
+
*/
|
|
4
|
+
import { Command } from 'commander';
|
|
5
|
+
import { getClient } from '../lib/api-client';
|
|
6
|
+
import { table, truncate } from '../lib/output';
|
|
7
|
+
export const searchCommand = new Command('search')
|
|
8
|
+
.description('Search across GitGate')
|
|
9
|
+
.argument('<query>', 'Search query')
|
|
10
|
+
.option('-s, --scope <scope>', 'Search scope (code/repos/issues/prs)', 'code')
|
|
11
|
+
.action(async (query, opts) => {
|
|
12
|
+
const client = getClient();
|
|
13
|
+
const params = new URLSearchParams({ q: query, scope: opts.scope });
|
|
14
|
+
const res = await client.get(`/api/search?${params}`);
|
|
15
|
+
if (res.data.length === 0) {
|
|
16
|
+
console.log(`No results for "${query}" in ${opts.scope}`);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
switch (opts.scope) {
|
|
20
|
+
case 'repos': {
|
|
21
|
+
const rows = res.data.map((r) => [
|
|
22
|
+
r.name,
|
|
23
|
+
truncate(r.description ?? '', 60),
|
|
24
|
+
]);
|
|
25
|
+
console.log(table(['REPO', 'DESCRIPTION'], rows));
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
case 'issues':
|
|
29
|
+
case 'prs': {
|
|
30
|
+
const rows = res.data.map((i) => [
|
|
31
|
+
`#${i.number}`,
|
|
32
|
+
truncate(i.title, 60),
|
|
33
|
+
i.state,
|
|
34
|
+
]);
|
|
35
|
+
console.log(table(['#', 'TITLE', 'STATE'], rows));
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
case 'code': {
|
|
39
|
+
for (const result of res.data) {
|
|
40
|
+
console.log(` ${result.path ?? 'unknown'} (score: ${result.score?.toFixed(3) ?? 'n/a'})`);
|
|
41
|
+
}
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEhD,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,uBAAuB,CAAC;KACpC,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC;KACnC,MAAM,CAAC,qBAAqB,EAAE,sCAAsC,EAAE,MAAM,CAAC;KAC7E,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;IAC5B,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IACpE,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,GAAG,CAC1B,eAAe,MAAM,EAAE,CACxB,CAAC;IAEF,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,mBAAmB,KAAK,QAAQ,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QAC1D,OAAO;IACT,CAAC;IAED,QAAQ,IAAI,CAAC,KAAK,EAAE,CAAC;QACnB,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,MAAM,IAAI,GAAI,GAAG,CAAC,IAAqD,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;gBACjF,CAAC,CAAC,IAAI;gBACN,QAAQ,CAAC,CAAC,CAAC,WAAW,IAAI,EAAE,EAAE,EAAE,CAAC;aAClC,CAAC,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;YAClD,MAAM;QACR,CAAC;QACD,KAAK,QAAQ,CAAC;QACd,KAAK,KAAK,CAAC,CAAC,CAAC;YACX,MAAM,IAAI,GAAI,GAAG,CAAC,IAAgE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;gBAC5F,IAAI,CAAC,CAAC,MAAM,EAAE;gBACd,QAAQ,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;gBACrB,CAAC,CAAC,KAAK;aACR,CAAC,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;YAClD,MAAM;QACR,CAAC;QACD,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,KAAK,MAAM,MAAM,IAAI,GAAG,CAAC,IAAiE,EAAE,CAAC;gBAC3F,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,IAAI,IAAI,SAAS,YAAY,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC;YAC7F,CAAC;YACD,MAAM;QACR,CAAC;IACH,CAAC;AACH,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gg viz — repository visualization commands.
|
|
3
|
+
*
|
|
4
|
+
* Terminal-friendly charts and summaries of repository statistics.
|
|
5
|
+
* All data comes from the GitGate API stats endpoint.
|
|
6
|
+
*
|
|
7
|
+
* gg viz <owner/repo> — Full summary dashboard
|
|
8
|
+
* gg viz activity <owner/repo> — Weekly activity timeline
|
|
9
|
+
* gg viz langs <owner/repo> — Language breakdown table
|
|
10
|
+
*/
|
|
11
|
+
import { Command } from 'commander';
|
|
12
|
+
export declare const vizCommand: Command;
|
|
13
|
+
//# sourceMappingURL=viz.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"viz.d.ts","sourceRoot":"","sources":["../../src/commands/viz.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwLpC,eAAO,MAAM,UAAU,SAYnB,CAAC"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gg viz — repository visualization commands.
|
|
3
|
+
*
|
|
4
|
+
* Terminal-friendly charts and summaries of repository statistics.
|
|
5
|
+
* All data comes from the GitGate API stats endpoint.
|
|
6
|
+
*
|
|
7
|
+
* gg viz <owner/repo> — Full summary dashboard
|
|
8
|
+
* gg viz activity <owner/repo> — Weekly activity timeline
|
|
9
|
+
* gg viz langs <owner/repo> — Language breakdown table
|
|
10
|
+
*/
|
|
11
|
+
import { Command } from 'commander';
|
|
12
|
+
import { isAuthenticated } from '../lib/config';
|
|
13
|
+
import { getClient } from '../lib/api-client';
|
|
14
|
+
import { table } from '../lib/output';
|
|
15
|
+
// ── Block characters for bar charts ──────────────────────────────────
|
|
16
|
+
const FULL = '\u2588'; // █
|
|
17
|
+
const LIGHT = '\u2591'; // ░
|
|
18
|
+
const MAX_BAR_WIDTH = 40;
|
|
19
|
+
// ── Helpers ──────────────────────────────────────────────────────────
|
|
20
|
+
function parseRepoArg(arg) {
|
|
21
|
+
const parts = arg.split('/');
|
|
22
|
+
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
23
|
+
console.error('Invalid repo format. Use: owner/repo');
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
return [parts[0], parts[1]];
|
|
27
|
+
}
|
|
28
|
+
function requireAuth() {
|
|
29
|
+
if (!isAuthenticated()) {
|
|
30
|
+
console.error('Not authenticated. Run: gg auth login');
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** Build a bar of full-block characters, proportional to value/max. */
|
|
35
|
+
function bar(value, max, width = MAX_BAR_WIDTH) {
|
|
36
|
+
if (max <= 0)
|
|
37
|
+
return '';
|
|
38
|
+
const len = Math.max(1, Math.round((value / max) * width));
|
|
39
|
+
return FULL.repeat(len);
|
|
40
|
+
}
|
|
41
|
+
/** Build the activity sparkline: █ for active weeks, ░ for inactive. */
|
|
42
|
+
function sparkline(weeks) {
|
|
43
|
+
return weeks.map((w) => (w.total > 0 ? FULL : LIGHT)).join('');
|
|
44
|
+
}
|
|
45
|
+
/** Format a date string as "Mon DD" (e.g. "Mar 3"). */
|
|
46
|
+
function shortDate(dateStr) {
|
|
47
|
+
const d = new Date(dateStr);
|
|
48
|
+
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
49
|
+
return `${months[d.getMonth()]} ${d.getDate()}`;
|
|
50
|
+
}
|
|
51
|
+
/** Format a number with comma separators (e.g. 125432 -> "125,432"). */
|
|
52
|
+
function formatNumber(n) {
|
|
53
|
+
return n.toLocaleString('en-US');
|
|
54
|
+
}
|
|
55
|
+
/** Pad a string on the right. */
|
|
56
|
+
function pad(str, width) {
|
|
57
|
+
return str.padEnd(width);
|
|
58
|
+
}
|
|
59
|
+
// ── Fetch stats ──────────────────────────────────────────────────────
|
|
60
|
+
async function fetchStats(owner, repo) {
|
|
61
|
+
const client = getClient();
|
|
62
|
+
const res = await client.get(`/api/repos/${owner}/${repo}/stats`);
|
|
63
|
+
return res.data;
|
|
64
|
+
}
|
|
65
|
+
// ── Renderers ────────────────────────────────────────────────────────
|
|
66
|
+
function renderSummary(stats) {
|
|
67
|
+
console.log(`${stats.owner}/${stats.repo} — Repository Insights`);
|
|
68
|
+
console.log('');
|
|
69
|
+
// ACTIVITY sparkline
|
|
70
|
+
const totalCommits = stats.commits;
|
|
71
|
+
const activityLine = sparkline(stats.activity);
|
|
72
|
+
console.log('ACTIVITY (last 90 days)');
|
|
73
|
+
console.log(` ${activityLine} ${totalCommits} commits`);
|
|
74
|
+
console.log('');
|
|
75
|
+
// LANGUAGES
|
|
76
|
+
if (stats.languages.length > 0) {
|
|
77
|
+
const maxPct = Math.max(...stats.languages.map((l) => l.percentage));
|
|
78
|
+
console.log('LANGUAGES');
|
|
79
|
+
const nameWidth = Math.max(...stats.languages.map((l) => l.name.length));
|
|
80
|
+
for (const lang of stats.languages) {
|
|
81
|
+
const barStr = bar(lang.percentage, maxPct, 20);
|
|
82
|
+
const pctStr = `${lang.percentage}%`.padStart(4);
|
|
83
|
+
console.log(` ${pad(lang.name, nameWidth)} ${pad(barStr, 20)} ${pctStr}`);
|
|
84
|
+
}
|
|
85
|
+
console.log('');
|
|
86
|
+
}
|
|
87
|
+
// TOP CONTRIBUTORS
|
|
88
|
+
if (stats.contributors.length > 0) {
|
|
89
|
+
const maxCommits = Math.max(...stats.contributors.map((c) => c.commits));
|
|
90
|
+
const nameWidth = Math.max(...stats.contributors.map((c) => c.name.length));
|
|
91
|
+
const emailWidth = Math.max(...stats.contributors.map((c) => c.email.length));
|
|
92
|
+
console.log('TOP CONTRIBUTORS');
|
|
93
|
+
for (const c of stats.contributors) {
|
|
94
|
+
const commitStr = `${c.commits} commits`.padEnd(12);
|
|
95
|
+
const barStr = bar(c.commits, maxCommits, 16);
|
|
96
|
+
console.log(` ${pad(c.name, nameWidth)} ${pad(c.email, emailWidth)} ${commitStr} ${barStr}`);
|
|
97
|
+
}
|
|
98
|
+
console.log('');
|
|
99
|
+
}
|
|
100
|
+
// STATS summary line
|
|
101
|
+
console.log('STATS');
|
|
102
|
+
console.log(` Commits: ${stats.commits}` +
|
|
103
|
+
` Files: ${stats.files}` +
|
|
104
|
+
` Branches: ${stats.branches}` +
|
|
105
|
+
` Tags: ${stats.tags}` +
|
|
106
|
+
` Contributors: ${stats.contributors.length}`);
|
|
107
|
+
}
|
|
108
|
+
function renderActivity(stats) {
|
|
109
|
+
if (stats.activity.length === 0) {
|
|
110
|
+
console.log('No activity data available.');
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
for (const week of stats.activity) {
|
|
114
|
+
const label = `Week of ${shortDate(week.weekOf)}:`;
|
|
115
|
+
const dayChars = week.days.map((d) => (d > 0 ? FULL : LIGHT)).join('');
|
|
116
|
+
console.log(`${label.padEnd(18)} ${dayChars} (${week.total} commits)`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function renderLanguages(stats) {
|
|
120
|
+
if (stats.languages.length === 0) {
|
|
121
|
+
console.log('No language data available.');
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const maxBytes = Math.max(...stats.languages.map((l) => l.bytes));
|
|
125
|
+
const rows = stats.languages.map((l) => [
|
|
126
|
+
l.name,
|
|
127
|
+
String(l.files),
|
|
128
|
+
formatNumber(l.bytes),
|
|
129
|
+
bar(l.bytes, maxBytes, 20),
|
|
130
|
+
]);
|
|
131
|
+
console.log(table(['LANGUAGE', 'FILES', 'BYTES', 'BAR'], rows));
|
|
132
|
+
}
|
|
133
|
+
// ── Command definition ───────────────────────────────────────────────
|
|
134
|
+
export const vizCommand = new Command('viz')
|
|
135
|
+
.description('Visualize repository statistics')
|
|
136
|
+
.argument('[repo]', 'owner/repo')
|
|
137
|
+
.action(async (repoArg) => {
|
|
138
|
+
if (!repoArg) {
|
|
139
|
+
console.error('Usage: gg viz <owner/repo>');
|
|
140
|
+
process.exit(1);
|
|
141
|
+
}
|
|
142
|
+
requireAuth();
|
|
143
|
+
const [owner, repo] = parseRepoArg(repoArg);
|
|
144
|
+
const stats = await fetchStats(owner, repo);
|
|
145
|
+
renderSummary(stats);
|
|
146
|
+
});
|
|
147
|
+
vizCommand
|
|
148
|
+
.command('activity')
|
|
149
|
+
.description('Show weekly activity timeline')
|
|
150
|
+
.argument('<repo>', 'owner/repo')
|
|
151
|
+
.action(async (repoArg) => {
|
|
152
|
+
requireAuth();
|
|
153
|
+
const [owner, repo] = parseRepoArg(repoArg);
|
|
154
|
+
const stats = await fetchStats(owner, repo);
|
|
155
|
+
renderActivity(stats);
|
|
156
|
+
});
|
|
157
|
+
vizCommand
|
|
158
|
+
.command('langs')
|
|
159
|
+
.description('Show language breakdown')
|
|
160
|
+
.argument('<repo>', 'owner/repo')
|
|
161
|
+
.action(async (repoArg) => {
|
|
162
|
+
requireAuth();
|
|
163
|
+
const [owner, repo] = parseRepoArg(repoArg);
|
|
164
|
+
const stats = await fetchStats(owner, repo);
|
|
165
|
+
renderLanguages(stats);
|
|
166
|
+
});
|
|
167
|
+
//# sourceMappingURL=viz.js.map
|