|
1 | 1 | import fg from "fast-glob"
|
2 | 2 | import fs from "fs/promises"
|
3 | 3 | import grayMatter from "gray-matter"
|
4 |
| -import { getGitHubStats } from "../scripts/sort-libraries/get-github-stats" |
| 4 | +import { |
| 5 | + getGitHubStats, |
| 6 | + type GitHubInfo, |
| 7 | +} from "../scripts/sort-libraries/get-github-stats" |
5 | 8 |
|
6 |
| -// todo: aggregate errors, merge results instead of overwriting |
7 | 9 | async function main() {
|
8 | 10 | const filePaths = await fg("./src/code/**/*.md")
|
9 | 11 |
|
10 |
| - const githubStats: Record<string, unknown> = {} |
| 12 | + const errors: Error[] = [] |
| 13 | + |
| 14 | + const newState = new Map<string /* repo name */, GitHubInfo>() |
| 15 | + const filePathToRepoName = new Map< |
| 16 | + string /* file path */, |
| 17 | + string /* repo name */ |
| 18 | + >() |
11 | 19 |
|
12 | 20 | for (const [index, filePath] of filePaths.entries()) {
|
13 |
| - const content = await fs.readFile(filePath, "utf8") |
14 |
| - const { data } = grayMatter(content) |
15 |
| - if (data.github) { |
16 |
| - githubStats[data.github] = await getGitHubStats(data.github) |
| 21 | + try { |
| 22 | + const content = await fs.readFile(filePath, "utf8") |
| 23 | + const { data } = grayMatter(content) |
| 24 | + if (data.github) { |
| 25 | + const stats = await getGitHubStats(data.github) |
| 26 | + if (stats) { |
| 27 | + newState.set(data.github, stats) |
| 28 | + } |
| 29 | + } |
| 30 | + console.info("✅ Done for", filePath, index + 1, "of", filePaths.length) |
| 31 | + } catch (err) { |
| 32 | + const error = err instanceof Error ? err : new Error(String(err)) |
| 33 | + errors.push(error) |
| 34 | + console.error( |
| 35 | + "❌ Error for", |
| 36 | + filePath, |
| 37 | + index + 1, |
| 38 | + "of", |
| 39 | + filePaths.length, |
| 40 | + err, |
| 41 | + ) |
| 42 | + } |
| 43 | + } |
| 44 | + |
| 45 | + if (errors.length > 0) { |
| 46 | + if (process.env.VERCEL) { |
| 47 | + console.error( |
| 48 | + "We don't want to fail the deployment, so we'll use the old github-stats.json file.", |
| 49 | + ) |
| 50 | + return |
| 51 | + } else { |
| 52 | + throw new Error("Errors occurred while fetching GitHub stats.") |
| 53 | + } |
| 54 | + } |
| 55 | + |
| 56 | + // If a .mdx file was removed, we also remove the package from the JSON. |
| 57 | + // If it errored for some reason, we don't do anything. |
| 58 | + // If we got it, we overwrite. |
| 59 | + { |
| 60 | + const dataPath = "./src/github-stats.json" |
| 61 | + const data = await fs.readFile(dataPath, "utf8") |
| 62 | + const existingStats = JSON.parse(data) as Record<string, object> |
| 63 | + |
| 64 | + const result: Record<string, object> = {} |
| 65 | + const brandNewKeys = new Set(newState.keys()) |
| 66 | + |
| 67 | + for (const [repoName, stats] of Object.entries(existingStats)) { |
| 68 | + const mdxFileExists = filePathToRepoName.has(repoName) |
| 69 | + if (mdxFileExists) { |
| 70 | + brandNewKeys.delete(repoName) |
| 71 | + result[repoName] = { |
| 72 | + ...stats, |
| 73 | + ...newState.get(repoName), |
| 74 | + } |
| 75 | + } |
17 | 76 | }
|
18 |
| - console.info("✅ Done for", filePath, index + 1, "of", filePaths.length) |
| 77 | + |
| 78 | + for (const repoName of brandNewKeys) { |
| 79 | + result[repoName] = newState.get(repoName)! |
| 80 | + } |
| 81 | + |
| 82 | + await fs.writeFile(dataPath, JSON.stringify(result, null, 2)) |
19 | 83 | }
|
20 |
| - await fs.writeFile( |
21 |
| - "./src/github-stats.json", |
22 |
| - JSON.stringify(githubStats, null, 2), |
23 |
| - ) |
24 | 84 | }
|
25 | 85 |
|
26 |
| -main() |
| 86 | +main().catch(() => process.exit(1)) |
0 commit comments