Skip to content

Commit 3db7df6

Browse files
updated components
1 parent c09ab3e commit 3db7df6

File tree

15 files changed

+365
-4208
lines changed

15 files changed

+365
-4208
lines changed

app/api/github/auth/route.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ export async function POST(request: NextRequest) {
2323
'Content-Type': 'application/json',
2424
},
2525
body: JSON.stringify({
26-
client_id: process.env.GITHUB_CLIENT_ID,
27-
client_secret: process.env.GITHUB_CLIENT_SECRET,
26+
client_id: process.env.NEXT_PUBLIC_GITHUB_CLIENT_ID,
27+
client_secret: process.env.NEXT_PUBLIC_GITHUB_CLIENT_SECRET,
2828
code,
2929
}),
3030
})

app/api/github/contents/route.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { NextRequest, NextResponse } from 'next/server'
2+
import { cookies } from 'next/headers'
3+
import { GitHubIntegration } from '@/lib/github-integration'
4+
5+
// Handler for creating or updating a file
6+
export async function PUT(req: NextRequest) {
7+
try {
8+
const cookieStore = await cookies() // Added await
9+
const githubToken = cookieStore.get('github_token')?.value
10+
11+
if (!githubToken) {
12+
return NextResponse.json({ error: 'GitHub token not found' }, { status: 401 })
13+
}
14+
15+
const { owner, repo, path, content, message, sha, branch } = await req.json()
16+
17+
if (!owner || !repo || !path || typeof content !== 'string' || !message) {
18+
return NextResponse.json({ error: 'Missing required parameters: owner, repo, path, content, message' }, { status: 400 })
19+
}
20+
21+
const github = new GitHubIntegration(githubToken)
22+
const result = await github.createOrUpdateFile(owner, repo, path, content, message, sha, branch)
23+
24+
if (result) {
25+
return NextResponse.json(result)
26+
} else {
27+
return NextResponse.json({ error: 'Failed to create or update file in GitHub' }, { status: 500 })
28+
}
29+
} catch (error: any) {
30+
console.error('Error in PUT /api/github/contents:', error)
31+
return NextResponse.json({ error: error.message || 'Internal Server Error' }, { status: 500 })
32+
}
33+
}
34+
35+
// Handler for deleting a file
36+
export async function DELETE(req: NextRequest) {
37+
try {
38+
const cookieStore = await cookies() // Added await
39+
const githubToken = cookieStore.get('github_token')?.value
40+
41+
if (!githubToken) {
42+
return NextResponse.json({ error: 'GitHub token not found' }, { status: 401 })
43+
}
44+
45+
const { owner, repo, path, message, sha, branch } = await req.json()
46+
47+
if (!owner || !repo || !path || !message || !sha) {
48+
return NextResponse.json({ error: 'Missing required parameters: owner, repo, path, message, sha' }, { status: 400 })
49+
}
50+
51+
const github = new GitHubIntegration(githubToken)
52+
const success = await github.deleteFile(owner, repo, path, message, sha, branch)
53+
54+
if (success) {
55+
return NextResponse.json({ message: 'File deleted successfully' })
56+
} else {
57+
return NextResponse.json({ error: 'Failed to delete file in GitHub' }, { status: 500 })
58+
}
59+
} catch (error: any) {
60+
console.error('Error in DELETE /api/github/contents:', error)
61+
return NextResponse.json({ error: error.message || 'Internal Server Error' }, { status: 500 })
62+
}
63+
}

lib/github-integration.ts

Lines changed: 111 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ interface GitHubFile {
1717
name: string
1818
path: string
1919
type: 'file' | 'dir'
20+
sha: string // Added SHA for file updates/deletions
2021
size?: number
2122
download_url?: string
2223
}
@@ -169,4 +170,113 @@ export class GitHubIntegration {
169170
await processDirectory()
170171
return files
171172
}
172-
}
173+
174+
async createOrUpdateFile(
175+
owner: string,
176+
repo: string,
177+
path: string,
178+
content: string,
179+
message: string,
180+
sha?: string, // SHA is needed for updating an existing file
181+
branch?: string
182+
): Promise<{ path: string; sha: string } | null> {
183+
try {
184+
const body: {
185+
message: string
186+
content: string
187+
sha?: string
188+
branch?: string
189+
} = {
190+
message,
191+
content: Buffer.from(content).toString('base64'), // Content must be base64 encoded
192+
}
193+
194+
if (sha) {
195+
body.sha = sha
196+
}
197+
if (branch) {
198+
body.branch = branch
199+
}
200+
201+
const response = await fetch(
202+
`https://api.github.com/repos/${owner}/${repo}/contents/${path}`,
203+
{
204+
method: 'PUT',
205+
headers: {
206+
'Authorization': `bearer ${this.accessToken}`,
207+
'Accept': 'application/vnd.github.v3+json',
208+
'Content-Type': 'application/json',
209+
},
210+
body: JSON.stringify(body),
211+
}
212+
)
213+
214+
if (!response.ok) {
215+
const errorData = await response.json()
216+
console.error('GitHub API error (createOrUpdateFile):', response.status, errorData)
217+
throw new Error(
218+
`GitHub API error: ${response.status} - ${errorData.message || 'Failed to create/update file'}`
219+
)
220+
}
221+
222+
const result = await response.json()
223+
return {
224+
path: result.content.path,
225+
sha: result.content.sha,
226+
}
227+
} catch (error) {
228+
console.error('Failed to create or update GitHub file:', error)
229+
return null
230+
}
231+
}
232+
233+
async deleteFile(
234+
owner: string,
235+
repo: string,
236+
path: string,
237+
message: string,
238+
sha: string, // SHA is required for deleting a file
239+
branch?: string
240+
): Promise<boolean> {
241+
try {
242+
const body: {
243+
message: string
244+
sha: string
245+
branch?: string
246+
} = {
247+
message,
248+
sha,
249+
}
250+
if (branch) {
251+
body.branch = branch
252+
}
253+
254+
const response = await fetch(
255+
`https://api.github.com/repos/${owner}/${repo}/contents/${path}`,
256+
{
257+
method: 'DELETE',
258+
headers: {
259+
'Authorization': `bearer ${this.accessToken}`,
260+
'Accept': 'application/vnd.github.v3+json',
261+
'Content-Type': 'application/json',
262+
},
263+
body: JSON.stringify(body),
264+
}
265+
)
266+
267+
if (!response.ok) {
268+
const errorData = await response.json()
269+
console.error('GitHub API error (deleteFile):', response.status, errorData)
270+
throw new Error(
271+
`GitHub API error: ${response.status} - ${errorData.message || 'Failed to delete file'}`
272+
)
273+
}
274+
// Successful deletion returns 200 OK with commit details or 204 No Content if the file didn't exist.
275+
// For simplicity, we'll consider it a success if response.ok is true.
276+
return true
277+
} catch (error) {
278+
console.error('Failed to delete GitHub file:', error)
279+
return false
280+
}
281+
}
282+
}

0 commit comments

Comments
 (0)