Files
renovate/lib/config/parse.ts
T
RahulGautamSingh 204a63d945 fix(config/parse): ignore trailing commas during jsonc validation (#44000)
* fix(config/parse): ignore trailing commas during jsonc validation

* use codeBlock for wrapping code
2026-06-15 06:35:18 +00:00

85 lines
2.6 KiB
TypeScript

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),
'$1',
);
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 };
}
}
}