import jsonValidator from 'json-dup-key-validator'; import JSON5 from 'json5'; import stripJsonComments from 'strip-json-comments'; import upath from 'upath'; import { logger } from '../logger/index.ts'; import { parseJson } from '../util/common.ts'; import { regEx } from '../util/regex.ts'; export function parseFileConfig( fileName: string, fileContents: string, ): | { success: true; parsedContents: unknown } | { success: false; validationError: string; validationMessage: string } { const fileType = upath.extname(fileName); if (fileType === '.json5') { try { return { success: true, parsedContents: JSON5.parse(fileContents) }; } catch (err) { logger.debug({ fileName, fileContents }, 'Error parsing JSON5 file'); const validationError = 'Invalid JSON5 (parsing failed)'; const validationMessage = `JSON5.parse error: \`${err.message.replaceAll( '`', "'", )}\``; return { success: false, validationError, validationMessage, }; } } else { // `json-dup-key-validator` is strict and rejects trailing commas, so we // strip them before validation. The actual parsing is handled by a lenient // JSONC parser which tolerates trailing commas. const jsonString = stripJsonComments(fileContents).replace( regEx(/,(?\s*[}\]])/g), '$', ); let allowDuplicateKeys = true; let jsonValidationError = jsonValidator.validate( jsonString, allowDuplicateKeys, ); if (jsonValidationError) { const validationError = 'Invalid JSON (parsing failed)'; const validationMessage = jsonValidationError; return { success: false, validationError, validationMessage, }; } allowDuplicateKeys = false; jsonValidationError = jsonValidator.validate( jsonString, allowDuplicateKeys, ); if (jsonValidationError) { const validationError = 'Duplicate keys in JSON'; const validationMessage = JSON.stringify(jsonValidationError); return { success: false, validationError, validationMessage, }; } try { return { success: true, parsedContents: parseJson(fileContents, fileName), }; } catch (err) { logger.debug({ fileContents }, 'Error parsing renovate config'); const validationError = 'Invalid JSON (parsing failed)'; const validationMessage = `JSON.parse error: \`${err.message.replaceAll( '`', "'", )}\``; return { success: false, validationError, validationMessage }; } } }