parseJsonWithSourceContext

JavaScript
import { readFile } from 'node:fs/promises';

// Parses JSON text and wraps V8 syntax errors with source and location context.
export function parseJsonText(text, source = 'JSON input') {
  try {
    return JSON.parse(text);
  } catch (error) {
    let location = '';
    const positionMatch = /position\s+(\d+)/i.exec(error.message);
    const lineColumnMatch = /line\s+(\d+)\s+column\s+(\d+)/i.exec(error.message);
    if (positionMatch) {
      const index = Number(positionMatch[1]);
      const before = text.slice(0, index);
      const line = before.split('\n').length;
      const column = index - before.lastIndexOf('\n');
      location = ` at line ${line}, column ${column}`;
    } else if (lineColumnMatch) {
      location = ` at line ${lineColumnMatch[1]}, column ${lineColumnMatch[2]}`;
    }
    throw new SyntaxError(`Cannot parse ${source}${location}: ${error.message}`, { cause: error });
  }
}

// Reads a UTF-8 file and parses it using the same diagnostics.
export async function parseJsonFile(path) {
  return parseJsonText(await readFile(path, 'utf8'), path);
}