-
Notifications
You must be signed in to change notification settings - Fork 0
/
mod.ts
113 lines (101 loc) · 2.66 KB
/
mod.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
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
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import { readLines } from "https://deno.land/[email protected]/io/mod.ts";
import * as tty from "https://deno.land/x/[email protected]/mod.ts";
const isatty = Deno.isatty(Deno.stdout.rid);
const list: { name: string; count: number; uniques: number }[] = [];
const print = () => {
list.sort((l, r) => {
const x = l.count - r.count;
if (x !== 0) {
return x;
}
return l.uniques - r.uniques;
});
console.table(list);
};
for await (const name of repos()) {
const { count, uniques } = await views(name);
list.push({ name, count, uniques });
if (isatty) {
await tty.clearScreen();
await tty.goHome();
print();
}
}
if (!isatty) {
print();
}
async function* repos(): AsyncGenerator<string, void, void> {
const query = `query($endCursor: String) {
viewer {
repositories(first: 10, after: $endCursor) {
nodes {
nameWithOwner
viewerCanUpdateTopics
}
pageInfo {
hasNextPage
endCursor
}
}
}
}`;
const filter = ".data.viewer.repositories.nodes[]";
const proc = Deno.run({
cmd: [
"gh",
"api",
"graphql",
"--paginate",
"-f",
`query=${query}`,
"--jq",
filter,
],
stdout: "piped",
});
function assertItem(
data: unknown,
): asserts data is { nameWithOwner: string; viewerCanUpdateTopics: boolean } {
const nameWithOwner = (data as Record<string, unknown>)["nameWithOwner"];
const viewerCanUpdateTopics =
(data as Record<string, unknown>)["viewerCanUpdateTopics"];
if (
typeof nameWithOwner !== "string" ||
typeof viewerCanUpdateTopics !== "boolean"
) {
throw new Error();
}
}
for await (const line of readLines(proc.stdout)) {
const data = JSON.parse(line);
assertItem(data);
const { nameWithOwner, viewerCanUpdateTopics } = data;
if (!viewerCanUpdateTopics) {
continue;
}
yield nameWithOwner;
}
}
async function views(
name: string,
): Promise<{ count: number; uniques: number }> {
const proc = Deno.run({
cmd: ["gh", "api", `repos/${name}/traffic/views`],
stdout: "piped",
});
const data = [];
for await (const line of readLines(proc.stdout)) {
data.push(line);
}
const status = await proc.status();
if (!status.success) {
throw new Error(data.join(""));
}
const c = JSON.parse(data.join(""));
const count = (c as Record<string, unknown>)["count"];
const uniques = (c as Record<string, unknown>)["uniques"];
if (typeof count !== "number" || typeof uniques !== "number") {
throw new Error();
}
return c;
}