Rename patterns/route-handler.md to docs/patterns/route-handler.md
This commit is contained in:
parent
98ca36e357
commit
a72944ecc3
1 changed files with 0 additions and 0 deletions
|
|
@ -1,90 +0,0 @@
|
|||
# Patroon: Route Handler (REST API)
|
||||
|
||||
Alle endpoints vereisen: `Authorization: Bearer <token>`
|
||||
|
||||
## lib/api-auth.ts
|
||||
|
||||
```ts
|
||||
import { createHash } from 'crypto'
|
||||
import { prisma } from '@/lib/prisma'
|
||||
|
||||
export async function authenticateApiRequest(request: Request) {
|
||||
const authHeader = request.headers.get('Authorization')
|
||||
if (!authHeader?.startsWith('Bearer ')) {
|
||||
return { error: 'Unauthorized', status: 401 }
|
||||
}
|
||||
|
||||
const token = authHeader.slice(7)
|
||||
const tokenHash = createHash('sha256').update(token).digest('hex')
|
||||
|
||||
const apiToken = await prisma.apiToken.findUnique({
|
||||
where: { token_hash: tokenHash },
|
||||
include: { user: true },
|
||||
})
|
||||
|
||||
if (!apiToken || apiToken.revoked_at) {
|
||||
return { error: 'Unauthorized', status: 401 }
|
||||
}
|
||||
|
||||
return { userId: apiToken.user_id, isDemo: apiToken.user.is_demo }
|
||||
}
|
||||
```
|
||||
|
||||
## Route Handler
|
||||
|
||||
```ts
|
||||
// app/api/products/[id]/next-story/route.ts
|
||||
import { authenticateApiRequest } from '@/lib/api-auth'
|
||||
import { prisma } from '@/lib/prisma'
|
||||
|
||||
export async function GET(
|
||||
request: Request,
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
const auth = await authenticateApiRequest(request)
|
||||
if ('error' in auth) {
|
||||
return Response.json({ error: auth.error }, { status: auth.status })
|
||||
}
|
||||
|
||||
const { id } = await params
|
||||
|
||||
const sprint = await prisma.sprint.findFirst({
|
||||
where: { product_id: id, status: 'ACTIVE', product: { user_id: auth.userId } },
|
||||
})
|
||||
if (!sprint) {
|
||||
return Response.json({ error: 'Geen actieve Sprint gevonden' }, { status: 404 })
|
||||
}
|
||||
|
||||
const story = await prisma.story.findFirst({
|
||||
where: { sprint_id: sprint.id, status: 'IN_SPRINT' },
|
||||
orderBy: [{ priority: 'asc' }, { sort_order: 'asc' }],
|
||||
include: { tasks: { orderBy: [{ priority: 'asc' }, { sort_order: 'asc' }] } },
|
||||
})
|
||||
|
||||
if (!story) {
|
||||
return Response.json({ error: 'Geen open stories in de Sprint' }, { status: 404 })
|
||||
}
|
||||
|
||||
return Response.json(story)
|
||||
}
|
||||
```
|
||||
|
||||
## POST /api/stories/:id/log — body schema
|
||||
|
||||
```json
|
||||
{ "type": "IMPLEMENTATION_PLAN", "content": "string" }
|
||||
{ "type": "TEST_RESULT", "content": "string", "status": "PASSED" | "FAILED" }
|
||||
{ "type": "COMMIT", "content": "string", "commit_hash": "string", "commit_message": "string" }
|
||||
```
|
||||
|
||||
## Alle endpoints
|
||||
|
||||
| Methode | Endpoint | Doel |
|
||||
|---|---|---|
|
||||
| GET | `/api/products` | Actieve producten ophalen |
|
||||
| GET | `/api/products/:id/next-story` | Hoogst geprioriteerde open story |
|
||||
| GET | `/api/sprints/:id/tasks?limit=10` | Eerste N taken van de Sprint |
|
||||
| PATCH | `/api/stories/:id/tasks/reorder` | Taakvolgorde aanpassen |
|
||||
| POST | `/api/stories/:id/log` | Plan / testresultaat / commit vastleggen |
|
||||
| PATCH | `/api/tasks/:id` | Taakstatus bijwerken |
|
||||
| POST | `/api/todos` | Todo aanmaken |
|
||||
Loading…
Add table
Add a link
Reference in a new issue