github.ts

1import { cache } from 'react'
2
3const USERNAME = 'chocoOnEstrogen'
4const BASE_URL = 'https://api.github.com'
5const TOKEN = process.env.GITHUB_TOKEN
6
7export const getProjects = cache(async () => {
8	const res = await fetch(`https://api.github.com/users/${USERNAME}/repos`, {
9		headers: {
10			Authorization: `token ${TOKEN}`,
11		},
12		next: { revalidate: 3600 }, // Cache for 1 hour
13	})
14
15	if (!res.ok) {
16		throw new Error('Failed to fetch projects')
17	}
18
19	const repos = await res.json()
20	return (
21		repos
22			// eslint-disable-next-line @typescript-eslint/no-explicit-any
23			.filter((repo: any) => repo.private === false)
24			// eslint-disable-next-line @typescript-eslint/no-explicit-any
25			.filter((repo: any) => repo.fork === false)
26			// eslint-disable-next-line @typescript-eslint/no-explicit-any
27			.filter((repo: any) => repo.name !== USERNAME)
28	)
29})
30
31export const getProjectDetails = cache(async (name: string) => {
32	const [repo, readme, contents] = await Promise.all([
33		// Get repository details
34		fetch(`${BASE_URL}/repos/${USERNAME}/${name}`, {
35			headers: { Authorization: `token ${TOKEN}` },
36			next: { revalidate: 3600 },
37		}).then((res) => res.json()),
38
39		// Get README content
40		fetch(`${BASE_URL}/repos/${USERNAME}/${name}/readme`, {
41			headers: {
42				Authorization: `token ${process.env.GITHUB_TOKEN}`,
43				Accept: 'application/vnd.github.raw',
44			},
45			next: { revalidate: 3600 },
46		}).then((res) => (res.ok ? res.text() : '')),
47
48		// Get repository contents
49		fetch(`${BASE_URL}/repos/${USERNAME}/${name}/contents`, {
50			headers: { Authorization: `token ${process.env.GITHUB_TOKEN}` },
51			next: { revalidate: 3600 },
52		}).then((res) => res.json()),
53	])
54
55	return {
56		...repo,
57		readme,
58		contents,
59	}
60})
61
62export const getBranches = cache(async (name: string) => {
63	const res = await fetch(`${BASE_URL}/repos/${USERNAME}/${name}/branches`, {
64		headers: { Authorization: `token ${TOKEN}` },
65		next: { revalidate: 3600 },
66	})
67
68	if (!res.ok) {
69		throw new Error('Failed to fetch branches')
70	}
71
72	return res.json()
73})
74
75export const getFileContent = cache(
76	async (name: string, path: string, branch = 'main') => {
77		const cleanPath = path.replace(/^\/+/, '')
78
79		const res = await fetch(
80			`${BASE_URL}/repos/${USERNAME}/${name}/contents/${cleanPath}?ref=${branch}`,
81			{
82				headers: {
83					Authorization: `token ${TOKEN}`,
84					Accept: 'application/vnd.github.raw',
85				},
86				next: { revalidate: 3600 },
87			},
88		)
89
90		if (!res.ok) {
91			throw new Error('Failed to fetch file content')
92		}
93
94		const content = await res.text()
95		return content
96	},
97)
98
99export const getDirContent = cache(
100	async (name: string, path: string, branch = 'main') => {
101		const cleanPath = path.replace(/^\/+/, '')
102
103		const res = await fetch(
104			`${BASE_URL}/repos/${USERNAME}/${name}/contents/${cleanPath}?ref=${branch}`,
105			{
106				headers: { Authorization: `token ${TOKEN}` },
107				next: { revalidate: 3600 },
108			},
109		)
110
111		if (!res.ok) {
112			throw new Error('Failed to fetch directory content')
113		}
114
115		const content = await res.json()
116		return content
117	},
118)
119
120export const getFileCommits = cache(
121	async (name: string, path: string, branch = 'main') => {
122		const cleanPath = path.replace(/^\/+/, '')
123
124		const res = await fetch(
125			`${BASE_URL}/repos/${USERNAME}/${name}/commits?path=${cleanPath}&sha=${branch}`,
126			{
127				headers: { Authorization: `token ${TOKEN}` },
128				next: { revalidate: 3600 },
129			},
130		)
131
132		if (!res.ok) {
133			throw new Error('Failed to fetch file commits')
134		}
135
136		return res.json()
137	},
138)
139