All files / web/src/app/api/admin/postcards route.ts

0% Statements 0/104
0% Branches 0/1
0% Functions 0/1
0% Lines 0/104

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105                                                                                                                                                                                                                 
/**
 * Admin Postcards API
 *
 * GET /api/admin/postcards - List recent postcards with their task trees
 */

import { NextResponse } from 'next/server'
import { desc, eq, inArray } from 'drizzle-orm'
import { db, schema } from '@/db'
import { withAuth } from '@/lib/auth/withAuth'

export const GET = withAuth(
  async (request) => {
    const url = new URL(request.url)
    const statusFilter = url.searchParams.get('status')
    const limit = Math.min(parseInt(url.searchParams.get('limit') ?? '50', 10), 100)

    // Fetch postcards
    let postcards = await db
      .select()
      .from(schema.numberLinePostcards)
      .orderBy(desc(schema.numberLinePostcards.createdAt))
      .limit(limit)
      .all()

    // Apply status filter if provided
    if (statusFilter) {
      postcards = postcards.filter((p) => p.status === statusFilter)
    }

    // Collect all task IDs from postcards
    const taskIds = postcards.map((p) => p.taskId).filter((id): id is string => id !== null)

    if (taskIds.length === 0) {
      return NextResponse.json({
        postcards: postcards.map((p) => ({
          ...p,
          manifest: p.manifest,
          parentTask: null,
          childTasks: [],
        })),
      })
    }

    // Fetch parent tasks
    const parentTasks = await db
      .select({
        id: schema.backgroundTasks.id,
        type: schema.backgroundTasks.type,
        status: schema.backgroundTasks.status,
        progress: schema.backgroundTasks.progress,
        progressMessage: schema.backgroundTasks.progressMessage,
        error: schema.backgroundTasks.error,
        output: schema.backgroundTasks.output,
        createdAt: schema.backgroundTasks.createdAt,
        startedAt: schema.backgroundTasks.startedAt,
        completedAt: schema.backgroundTasks.completedAt,
      })
      .from(schema.backgroundTasks)
      .where(inArray(schema.backgroundTasks.id, taskIds))
      .all()

    const parentTaskMap = new Map(parentTasks.map((t) => [t.id, t]))

    // Fetch child tasks for all parent task IDs
    const childTasks = await db
      .select({
        id: schema.backgroundTasks.id,
        type: schema.backgroundTasks.type,
        status: schema.backgroundTasks.status,
        progress: schema.backgroundTasks.progress,
        progressMessage: schema.backgroundTasks.progressMessage,
        error: schema.backgroundTasks.error,
        output: schema.backgroundTasks.output,
        createdAt: schema.backgroundTasks.createdAt,
        startedAt: schema.backgroundTasks.startedAt,
        completedAt: schema.backgroundTasks.completedAt,
        parentTaskId: schema.backgroundTasks.parentTaskId,
      })
      .from(schema.backgroundTasks)
      .where(inArray(schema.backgroundTasks.parentTaskId, taskIds))
      .all()

    // Group child tasks by parent
    const childTasksByParent = new Map<string, typeof childTasks>()
    for (const child of childTasks) {
      if (!child.parentTaskId) continue
      const existing = childTasksByParent.get(child.parentTaskId) ?? []
      existing.push(child)
      childTasksByParent.set(child.parentTaskId, existing)
    }

    // Assemble response
    const result = postcards.map((p) => ({
      ...p,
      manifest: p.manifest,
      parentTask: p.taskId ? (parentTaskMap.get(p.taskId) ?? null) : null,
      childTasks: p.taskId ? (childTasksByParent.get(p.taskId) ?? []) : [],
    }))

    return NextResponse.json({ postcards: result })
  },
  { role: 'admin' }
)