(request: NextRequest)
| 128 | const ALLOWED_REPOS = [WORKSPACE + '/mission-control', WORKSPACE]; |
| 129 | |
| 130 | export async function POST(request: NextRequest) { |
| 131 | try { |
| 132 | const body = await request.json(); |
| 133 | const { repo, action } = body; |
| 134 | |
| 135 | // Security: only allow repos under workspace |
| 136 | if (!repo || !repo.startsWith(WORKSPACE)) { |
| 137 | return NextResponse.json({ error: 'Invalid repo path' }, { status: 400 }); |
| 138 | } |
| 139 | |
| 140 | let output = ''; |
| 141 | |
| 142 | switch (action) { |
| 143 | case 'status': { |
| 144 | const { stdout } = await execAsync(`cd "${repo}" && git status 2>&1`); |
| 145 | output = stdout; |
| 146 | break; |
| 147 | } |
| 148 | case 'pull': { |
| 149 | const { stdout } = await execAsync(`cd "${repo}" && git pull 2>&1`); |
| 150 | output = stdout; |
| 151 | break; |
| 152 | } |
| 153 | case 'log': { |
| 154 | const { stdout } = await execAsync(`cd "${repo}" && git log --oneline -20 2>&1`); |
| 155 | output = stdout; |
| 156 | break; |
| 157 | } |
| 158 | case 'diff': { |
| 159 | const { stdout } = await execAsync(`cd "${repo}" && git diff --stat 2>&1`); |
| 160 | output = stdout || 'No changes'; |
| 161 | break; |
| 162 | } |
| 163 | default: |
| 164 | return NextResponse.json({ error: 'Unknown action' }, { status: 400 }); |
| 165 | } |
| 166 | |
| 167 | return NextResponse.json({ success: true, output, repo, action }); |
| 168 | } catch (error) { |
| 169 | return NextResponse.json({ error: String(error) }, { status: 500 }); |
| 170 | } |
| 171 | } |
nothing calls this directly
no outgoing calls
no test coverage detected