import { getErrorMessage } from '@sim/utils/errors' import type { FileParseResult } from '@/lib/file-parsers/types' /** * Parse JSON files */ export async function parseJSON(filePath: string): Promise { const fs = await import('fs/promises') const content = await fs.readFile(filePath, 'utf-8') try { // Parse to validate JSON const jsonData = JSON.parse(content) // Return pretty-printed JSON for better readability const formattedContent = JSON.stringify(jsonData, null, 2) // Extract metadata about the JSON structure const metadata = { type: 'json', isArray: Array.isArray(jsonData), keys: Array.isArray(jsonData) ? [] : Object.keys(jsonData), itemCount: Array.isArray(jsonData) ? jsonData.length : undefined, depth: getJsonDepth(jsonData), } return { content: formattedContent, metadata, } } catch (error) { throw new Error(`Invalid JSON: ${getErrorMessage(error, 'Unknown error')}`) } } /** * Parse JSON from buffer */ export async function parseJSONBuffer(buffer: Buffer): Promise { const content = buffer.toString('utf-8') try { const jsonData = JSON.parse(content) const formattedContent = JSON.stringify(jsonData, null, 2) const metadata = { type: 'json', isArray: Array.isArray(jsonData), keys: Array.isArray(jsonData) ? [] : Object.keys(jsonData), itemCount: Array.isArray(jsonData) ? jsonData.length : undefined, depth: getJsonDepth(jsonData), } return { content: formattedContent, metadata, } } catch (error) { throw new Error(`Invalid JSON: ${getErrorMessage(error, 'Unknown error')}`) } } /** * Parse JSONL (JSON Lines) files — one JSON object per line */ export async function parseJSONL(filePath: string): Promise { const fs = await import('fs/promises') const content = await fs.readFile(filePath, 'utf-8') return parseJSONLContent(content) } /** * Parse JSONL from buffer */ export async function parseJSONLBuffer(buffer: Buffer): Promise { const content = buffer.toString('utf-8') return parseJSONLContent(content) } function parseJSONLContent(content: string): FileParseResult { const lines = content.split('\n').filter((line) => line.trim()) const items: unknown[] = [] for (const line of lines) { try { items.push(JSON.parse(line)) } catch { throw new Error(`Invalid JSONL: failed to parse line: ${line.slice(0, 100)}`) } } const formattedContent = JSON.stringify(items, null, 2) return { content: formattedContent, metadata: { type: 'json', isArray: true, keys: [], itemCount: items.length, depth: items.length > 0 ? 1 + getJsonDepth(items[0]) : 1, }, } } /** * Calculate the depth of a JSON object */ function getJsonDepth(obj: any): number { if (obj === null || typeof obj !== 'object') return 0 if (Array.isArray(obj)) { return obj.length > 0 ? 1 + Math.max(...obj.map(getJsonDepth)) : 1 } const depths = Object.values(obj).map(getJsonDepth) return depths.length > 0 ? 1 + Math.max(...depths) : 1 }