import { createLogger } from '@sim/logger' import { getErrorMessage } from '@sim/utils/errors' import { type NextRequest, NextResponse } from 'next/server' import { pipedriveGetFilesContract } from '@/lib/api/contracts/tools/pipedrive' import { parseRequest } from '@/lib/api/server' import { checkInternalAuth } from '@/lib/auth/hybrid' import { secureFetchWithPinnedIP, validateUrlWithDNS, } from '@/lib/core/security/input-validation.server' import { generateRequestId } from '@/lib/core/utils/request' import { withRouteHandler } from '@/lib/core/utils/with-route-handler' import { getFileExtension, getMimeTypeFromExtension } from '@/lib/uploads/utils/file-utils' export const dynamic = 'force-dynamic' const logger = createLogger('PipedriveGetFilesAPI') interface PipedriveFile { id?: number name?: string url?: string } interface PipedriveApiResponse { success: boolean data?: PipedriveFile[] additional_data?: { pagination?: { more_items_in_collection: boolean next_start: number } } error?: string } export const POST = withRouteHandler(async (request: NextRequest) => { const requestId = generateRequestId() try { const authResult = await checkInternalAuth(request, { requireWorkflowId: false }) if (!authResult.success) { logger.warn(`[${requestId}] Unauthorized Pipedrive get files attempt: ${authResult.error}`) return NextResponse.json( { success: false, error: authResult.error || 'Authentication required', }, { status: 401 } ) } const parsed = await parseRequest(pipedriveGetFilesContract, request, {}) if (!parsed.success) return parsed.response const { accessToken, sort, limit, start, downloadFiles } = parsed.data.body const baseUrl = 'https://api.pipedrive.com/v1/files' const queryParams = new URLSearchParams() if (sort) queryParams.append('sort', sort) if (limit) queryParams.append('limit', limit) if (start) queryParams.append('start', start) const queryString = queryParams.toString() const apiUrl = queryString ? `${baseUrl}?${queryString}` : baseUrl logger.info(`[${requestId}] Fetching files from Pipedrive`) const urlValidation = await validateUrlWithDNS(apiUrl, 'apiUrl') if (!urlValidation.isValid) { return NextResponse.json({ success: false, error: urlValidation.error }, { status: 400 }) } const response = await secureFetchWithPinnedIP(apiUrl, urlValidation.resolvedIP!, { method: 'GET', headers: { Authorization: `Bearer ${accessToken}`, Accept: 'application/json', }, }) const data = (await response.json()) as PipedriveApiResponse if (!data.success) { logger.error(`[${requestId}] Pipedrive API request failed`, { data }) return NextResponse.json( { success: false, error: data.error || 'Failed to fetch files from Pipedrive' }, { status: 400 } ) } const files = data.data || [] const hasMore = data.additional_data?.pagination?.more_items_in_collection || false const nextStart = data.additional_data?.pagination?.next_start ?? null const downloadedFiles: Array<{ name: string mimeType: string data: string size: number }> = [] if (downloadFiles) { for (const file of files) { if (!file?.url) continue try { const fileUrlValidation = await validateUrlWithDNS(file.url, 'fileUrl') if (!fileUrlValidation.isValid) continue const downloadResponse = await secureFetchWithPinnedIP( file.url, fileUrlValidation.resolvedIP!, { method: 'GET', headers: { Authorization: `Bearer ${accessToken}` }, } ) if (!downloadResponse.ok) continue const arrayBuffer = await downloadResponse.arrayBuffer() const buffer = Buffer.from(arrayBuffer) const extension = getFileExtension(file.name || '') const mimeType = downloadResponse.headers.get('content-type') || getMimeTypeFromExtension(extension) const fileName = file.name || `pipedrive-file-${file.id || Date.now()}` downloadedFiles.push({ name: fileName, mimeType, data: buffer.toString('base64'), size: buffer.length, }) } catch (error) { logger.warn(`[${requestId}] Failed to download file ${file.id}:`, error) } } } logger.info(`[${requestId}] Pipedrive files fetched successfully`, { fileCount: files.length, downloadedCount: downloadedFiles.length, }) return NextResponse.json({ success: true, output: { files, downloadedFiles: downloadedFiles.length > 0 ? downloadedFiles : undefined, total_items: files.length, has_more: hasMore, next_start: nextStart, success: true, }, }) } catch (error) { logger.error(`[${requestId}] Error fetching Pipedrive files:`, error) return NextResponse.json( { success: false, error: getErrorMessage(error, 'Unknown error occurred'), }, { status: 500 } ) } })