import { NextRequest, NextResponse } from 'next/server'; import { previewSetupCsvImport } from '@/features/setup/server/csv-preview.service'; import { assertBootstrapStepFiles, assertBootstrapSetupAvailable, assertBootstrapToken, BOOTSTRAP_ACTOR_ID, BootstrapSetupError, setupStepStatusFromPreview, toSerializableRecord } from '@/features/setup/server/setup-bootstrap.service'; import { saveSetupStep, startSetupRun } from '@/features/setup/server/setup-state.service'; function isFile(value: FormDataEntryValue): value is File { return ( typeof value === 'object' && 'arrayBuffer' in value && 'name' in value && typeof value.name === 'string' && value.name.trim().length > 0 ); } export async function POST(request: NextRequest) { try { await assertBootstrapSetupAvailable(); const formData = await request.formData(); assertBootstrapToken(String(formData.get('bootstrapToken') ?? request.headers.get('x-bootstrap-setup-token') ?? '')); const stepKey = String(formData.get('stepKey') ?? ''); const uploadedFiles = Array.from(formData.values()).filter(isFile); if (uploadedFiles.length === 0) { return NextResponse.json({ message: 'Upload at least one setup CSV file using multipart/form-data.' }, { status: 400 }); } const files = await Promise.all( uploadedFiles.map(async (file) => ({ fileName: file.name, bytes: new Uint8Array(await file.arrayBuffer()) })) ); const step = assertBootstrapStepFiles(stepKey, files); await startSetupRun({ actorId: BOOTSTRAP_ACTOR_ID, mode: 'production', targetOrganizationId: null }); const preview = await previewSetupCsvImport(files); await saveSetupStep({ stepKey: step.stepKey, status: setupStepStatusFromPreview(preview), inputHash: preview.previewHash, output: toSerializableRecord(preview), errors: preview.files.flatMap((file) => file.errors), warnings: preview.files.flatMap((file) => file.warnings) }); return NextResponse.json(preview); } catch (error) { if (error instanceof BootstrapSetupError) { return NextResponse.json({ message: error.message, details: error.details }, { status: error.status }); } if (error instanceof TypeError && /multipart\/form-data|application\/x-www-form-urlencoded/i.test(error.message)) { return NextResponse.json({ message: 'Upload setup CSV files using multipart/form-data.' }, { status: 400 }); } console.error('Bootstrap preview failed'); if (error instanceof Error) { for (const line of (error.stack ?? error.message).split('\n').slice(0, 12)) { console.error(line); } } else { console.error(error); } return NextResponse.json({ message: 'Unable preview bootstrap setup CSV import' }, { status: 500 }); } }