github-search-cli 9.4.1 → 9.4.3
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/CHANGELOG.md +65 -1
- package/README.md +268 -237
- package/bin/ghfind.js +98 -89
- package/completions/ghfind.bash +1 -1
- package/completions/ghfind.fish +3 -1
- package/completions/ghfind.zsh +6 -0
- package/dist/{chunk-IVUU2KGR.js → chunk-GYIL4S5X.js} +4 -1
- package/dist/cli.js +1179 -403
- package/dist/{config-GNZOQRTH.js → config-OCIPF2IF.js} +1 -1
- package/package.json +16 -5
- package/release-notes/9.3.0.md +32 -29
- package/scripts/build.ts +34 -19
- package/scripts/generate-svg-demo.js +218 -168
- package/scripts/postinstall.js +176 -176
- package/src/bookmarks.ts +69 -69
- package/src/cli.ts +650 -566
- package/src/compare.ts +69 -47
- package/src/config.ts +70 -65
- package/src/deepdive.ts +149 -118
- package/src/doctor.ts +287 -287
- package/src/error-report.ts +8 -12
- package/src/errors.ts +62 -59
- package/src/explore.ts +34 -29
- package/src/export.ts +73 -63
- package/src/help.ts +157 -157
- package/src/history.ts +69 -55
- package/src/init.ts +60 -55
- package/src/landing.ts +106 -104
- package/src/login.ts +186 -0
- package/src/markdown-render.ts +1 -6
- package/src/notifications.ts +75 -59
- package/src/open-url.ts +16 -16
- package/src/org.ts +299 -0
- package/src/output.ts +153 -137
- package/src/package-browser.ts +317 -305
- package/src/package.ts +149 -137
- package/src/pipe.ts +60 -54
- package/src/releases.ts +182 -144
- package/src/saved-searches.ts +72 -50
- package/src/search-state.ts +283 -229
- package/src/search.ts +678 -653
- package/src/session.ts +26 -24
- package/src/share.ts +61 -54
- package/src/status.ts +68 -61
- package/src/storage.ts +136 -106
- package/src/themes.ts +259 -116
- package/src/tips.ts +42 -42
- package/src/toast.ts +70 -69
- package/src/trending-parser.ts +104 -0
- package/src/trending.ts +481 -462
- package/src/tui.ts +3015 -2867
- package/src/types.ts +160 -158
- package/src/update-check.ts +231 -215
- package/src/version.ts +33 -0
- package/src/watch.ts +95 -74
package/src/output.ts
CHANGED
|
@@ -1,137 +1,153 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Output module — unified formatting, export, and pipe execution.
|
|
3
|
-
*
|
|
4
|
-
* All format functions (JSON, CSV, Markdown, text, urls, names, ssh-urls,
|
|
5
|
-
* clone-commands, ids) register in a single registry. One `format()` function
|
|
6
|
-
* dispatches. `exportToFile` and `pipeExec` are methods on the same module.
|
|
7
|
-
*/
|
|
8
|
-
import { writeFileSync } from "fs";
|
|
9
|
-
import type { Repo } from "./types";
|
|
10
|
-
import { openUrl } from "./open-url";
|
|
11
|
-
|
|
12
|
-
export type Format =
|
|
13
|
-
| "json"
|
|
14
|
-
| "
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
["
|
|
29
|
-
["
|
|
30
|
-
["
|
|
31
|
-
]
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
return
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Output module — unified formatting, export, and pipe execution.
|
|
3
|
+
*
|
|
4
|
+
* All format functions (JSON, CSV, Markdown, text, urls, names, ssh-urls,
|
|
5
|
+
* clone-commands, ids) register in a single registry. One `format()` function
|
|
6
|
+
* dispatches. `exportToFile` and `pipeExec` are methods on the same module.
|
|
7
|
+
*/
|
|
8
|
+
import { writeFileSync } from "fs";
|
|
9
|
+
import type { Repo } from "./types";
|
|
10
|
+
import { openUrl } from "./open-url";
|
|
11
|
+
|
|
12
|
+
export type Format =
|
|
13
|
+
| "json"
|
|
14
|
+
| "csv"
|
|
15
|
+
| "markdown"
|
|
16
|
+
| "text"
|
|
17
|
+
| "urls"
|
|
18
|
+
| "names"
|
|
19
|
+
| "ssh-urls"
|
|
20
|
+
| "clone-commands"
|
|
21
|
+
| "ids";
|
|
22
|
+
|
|
23
|
+
export type FormatFn = (repos: Repo[]) => string;
|
|
24
|
+
|
|
25
|
+
/** Registry of all format functions. Adding a format = 1 line here. */
|
|
26
|
+
const FORMATS: Map<Format, FormatFn> = new Map([
|
|
27
|
+
// Export formats
|
|
28
|
+
["json", formatJson],
|
|
29
|
+
["csv", formatCsv],
|
|
30
|
+
["markdown", formatMarkdown],
|
|
31
|
+
["text", formatText],
|
|
32
|
+
// Pipe formats
|
|
33
|
+
["urls", formatUrls],
|
|
34
|
+
["names", formatNames],
|
|
35
|
+
["ssh-urls", formatSshUrls],
|
|
36
|
+
["clone-commands", formatCloneCommands],
|
|
37
|
+
["ids", formatIds],
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
// ── Export format functions ────────────────────────────────────────────
|
|
41
|
+
|
|
42
|
+
export function formatJson(repos: Repo[]): string {
|
|
43
|
+
return JSON.stringify(repos, null, 2);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function csvEscape(val: unknown): string {
|
|
47
|
+
const str = String(val ?? "");
|
|
48
|
+
if (str.includes('"') || str.includes(",") || str.includes("\n")) {
|
|
49
|
+
return `"${str.replace(/"/g, '""')}"`;
|
|
50
|
+
}
|
|
51
|
+
return str;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function formatCsv(repos: Repo[]): string {
|
|
55
|
+
const header = "rank,full_name,stars,forks,language,url";
|
|
56
|
+
const rows = repos.map(
|
|
57
|
+
(r, i) =>
|
|
58
|
+
`${i + 1},${csvEscape(r.fullName)},${r.stars},${r.forks},${csvEscape(r.language ?? "")},${csvEscape(r.url)}`,
|
|
59
|
+
);
|
|
60
|
+
return [header, ...rows].join("\n");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function formatMarkdown(repos: Repo[]): string {
|
|
64
|
+
const header = "| # | Repo | Stars | Forks | Language |";
|
|
65
|
+
const sep = "|---|------|-------|-------|----------|";
|
|
66
|
+
const rows = repos.map(
|
|
67
|
+
(r, i) =>
|
|
68
|
+
`| ${i + 1} | [${r.fullName}](${r.url}) | ${r.stars.toLocaleString()} | ${r.forks.toLocaleString()} | ${r.language ?? "—"} |`,
|
|
69
|
+
);
|
|
70
|
+
return [header, sep, ...rows].join("\n");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function formatText(repos: Repo[]): string {
|
|
74
|
+
return repos
|
|
75
|
+
.map(
|
|
76
|
+
(r, i) =>
|
|
77
|
+
`${i + 1}. ${r.fullName} ★ ${r.stars.toLocaleString()} ${r.url}`,
|
|
78
|
+
)
|
|
79
|
+
.join("\n");
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// ── Pipe format functions ──────────────────────────────────────────────
|
|
83
|
+
|
|
84
|
+
export function formatUrls(repos: Repo[]): string {
|
|
85
|
+
return repos.map((r) => r.url).join("\n");
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function formatNames(repos: Repo[]): string {
|
|
89
|
+
return repos.map((r) => r.fullName).join("\n");
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function formatSshUrls(repos: Repo[]): string {
|
|
93
|
+
return repos.map((r) => `git@github.com:${r.fullName}.git`).join("\n");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function formatCloneCommands(repos: Repo[]): string {
|
|
97
|
+
return repos
|
|
98
|
+
.map((r) => `git clone git@github.com:${r.fullName}.git`)
|
|
99
|
+
.join("\n");
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function formatIds(repos: Repo[]): string {
|
|
103
|
+
return repos.map((r) => String(r.id)).join("\n");
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ── Public API ─────────────────────────────────────────────────────────
|
|
107
|
+
|
|
108
|
+
/** Format repos using the registered format function. */
|
|
109
|
+
export function format(repos: Repo[], format: Format): string {
|
|
110
|
+
const fn = FORMATS.get(format);
|
|
111
|
+
if (!fn) throw new Error(`Unknown format: ${format}`);
|
|
112
|
+
return fn(repos);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Export repos to a file. Returns the file path. */
|
|
116
|
+
export function exportToFile(repos: Repo[], fmt: Format): string {
|
|
117
|
+
const ext = fmt === "markdown" ? "md" : fmt;
|
|
118
|
+
const ts = Date.now();
|
|
119
|
+
const path = `./ghfind-export-${ts}.${ext}`;
|
|
120
|
+
writeFileSync(path, format(repos, fmt), "utf-8");
|
|
121
|
+
return path;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** Execute a pipe target (clone, open) on repos. */
|
|
125
|
+
export async function pipeExec(repos: Repo[], target: string): Promise<void> {
|
|
126
|
+
for (const repo of repos) {
|
|
127
|
+
const url = repo.url;
|
|
128
|
+
switch (target) {
|
|
129
|
+
case "open":
|
|
130
|
+
await openUrl(url);
|
|
131
|
+
break;
|
|
132
|
+
case "clone":
|
|
133
|
+
console.log(`git clone git@github.com:${repo.fullName}.git`);
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ─── Backward-compatible re-exports ─────────────────────────────────────
|
|
140
|
+
|
|
141
|
+
export type ExportFormat = "json" | "csv" | "markdown" | "text";
|
|
142
|
+
export type FormatLine =
|
|
143
|
+
"urls" | "names" | "ssh-urls" | "clone-commands" | "ids";
|
|
144
|
+
|
|
145
|
+
/** @deprecated Use `format()` instead. */
|
|
146
|
+
export function formatRepos(repos: Repo[], fmt: ExportFormat): string {
|
|
147
|
+
return format(repos, fmt);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** @deprecated Use `format()` instead. */
|
|
151
|
+
export function formatLines(repos: Repo[], fmt: FormatLine): string {
|
|
152
|
+
return format(repos, fmt);
|
|
153
|
+
}
|