@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.
Files changed (49) hide show
  1. package/dist/commands/actions.d.ts +11 -0
  2. package/dist/commands/actions.d.ts.map +1 -0
  3. package/dist/commands/actions.js +97 -0
  4. package/dist/commands/actions.js.map +1 -0
  5. package/dist/commands/auth.d.ts +11 -0
  6. package/dist/commands/auth.d.ts.map +1 -0
  7. package/dist/commands/auth.js +104 -0
  8. package/dist/commands/auth.js.map +1 -0
  9. package/dist/commands/import.d.ts +10 -0
  10. package/dist/commands/import.d.ts.map +1 -0
  11. package/dist/commands/import.js +101 -0
  12. package/dist/commands/import.js.map +1 -0
  13. package/dist/commands/issue.d.ts +12 -0
  14. package/dist/commands/issue.d.ts.map +1 -0
  15. package/dist/commands/issue.js +140 -0
  16. package/dist/commands/issue.js.map +1 -0
  17. package/dist/commands/pr.d.ts +14 -0
  18. package/dist/commands/pr.d.ts.map +1 -0
  19. package/dist/commands/pr.js +150 -0
  20. package/dist/commands/pr.js.map +1 -0
  21. package/dist/commands/repo.d.ts +19 -0
  22. package/dist/commands/repo.d.ts.map +1 -0
  23. package/dist/commands/repo.js +199 -0
  24. package/dist/commands/repo.js.map +1 -0
  25. package/dist/commands/search.d.ts +6 -0
  26. package/dist/commands/search.d.ts.map +1 -0
  27. package/dist/commands/search.js +46 -0
  28. package/dist/commands/search.js.map +1 -0
  29. package/dist/commands/viz.d.ts +13 -0
  30. package/dist/commands/viz.d.ts.map +1 -0
  31. package/dist/commands/viz.js +167 -0
  32. package/dist/commands/viz.js.map +1 -0
  33. package/dist/index.d.ts +9 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +34 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/lib/api-client.d.ts +23 -0
  38. package/dist/lib/api-client.d.ts.map +1 -0
  39. package/dist/lib/api-client.js +79 -0
  40. package/dist/lib/api-client.js.map +1 -0
  41. package/dist/lib/config.d.ts +16 -0
  42. package/dist/lib/config.d.ts.map +1 -0
  43. package/dist/lib/config.js +44 -0
  44. package/dist/lib/config.js.map +1 -0
  45. package/dist/lib/output.d.ts +8 -0
  46. package/dist/lib/output.d.ts.map +1 -0
  47. package/dist/lib/output.js +46 -0
  48. package/dist/lib/output.js.map +1 -0
  49. 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":"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"}
@@ -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,6 @@
1
+ /**
2
+ * gg search — search across code, repos, issues, PRs.
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare const searchCommand: Command;
6
+ //# sourceMappingURL=search.d.ts.map
@@ -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