Skip to content

Commit ce149bd

Browse files
committed
feat(upload): preview API route with schema detection
1 parent 69ca8a2 commit ce149bd

1 file changed

Lines changed: 71 additions & 0 deletions

File tree

  • codebenders-dashboard/app/api/admin/upload/preview
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { NextRequest, NextResponse } from "next/server"
2+
import { parseFileBuffer, getFileType, validateFileSize } from "@/lib/upload-parser"
3+
import { detectSchema, mapColumns } from "@/lib/upload-schemas"
4+
5+
export async function POST(request: NextRequest) {
6+
try {
7+
const formData = await request.formData()
8+
const file = formData.get("file") as File | null
9+
10+
if (!file) {
11+
return NextResponse.json({ error: "No file provided" }, { status: 400 })
12+
}
13+
14+
if (!validateFileSize(file.size)) {
15+
return NextResponse.json(
16+
{ error: "File exceeds 50 MB limit" },
17+
{ status: 413 }
18+
)
19+
}
20+
21+
const fileType = getFileType(file.name)
22+
if (!fileType) {
23+
return NextResponse.json(
24+
{ error: "Unsupported file type. Please upload a .csv or .xlsx file." },
25+
{ status: 400 }
26+
)
27+
}
28+
29+
const buffer = Buffer.from(await file.arrayBuffer())
30+
const { headers, rows, totalRows } = await parseFileBuffer(buffer, fileType, 50)
31+
32+
const detection = detectSchema(headers)
33+
34+
const columns = detection.schema
35+
? mapColumns(headers, detection.schema)
36+
: headers.map((h) => ({ header: h, mappedTo: null, status: "unmapped" as const }))
37+
38+
const missingRequired = detection.schema
39+
? detection.schema.columns
40+
.filter((c) => c.required)
41+
.filter((c) => !columns.some((col) => col.mappedTo === c.name))
42+
.map((c) => `Missing required column: ${c.name}`)
43+
: []
44+
45+
const warnings = detection.schema
46+
? detection.schema.columns
47+
.filter((c) => !c.required)
48+
.filter((c) => !columns.some((col) => col.mappedTo === c.name))
49+
.slice(0, 5)
50+
.map((c) => `Missing optional column: ${c.name}`)
51+
: []
52+
53+
return NextResponse.json({
54+
detectedSchema: detection.schema?.id ?? null,
55+
detectedSchemaLabel: detection.schema?.label ?? null,
56+
confidence: Math.round(detection.confidence * 100) / 100,
57+
scores: detection.scores,
58+
columns,
59+
sampleRows: rows.slice(0, 10),
60+
totalRows,
61+
warnings,
62+
errors: missingRequired,
63+
})
64+
} catch (err) {
65+
console.error("Upload preview error:", err)
66+
return NextResponse.json(
67+
{ error: `Failed to parse file: ${(err as Error).message}` },
68+
{ status: 500 }
69+
)
70+
}
71+
}

0 commit comments

Comments
 (0)