declapract
Version:
A tool to declaratively define best practices, maintainable evolve them, and scalably enforce them.
140 lines • 7.24 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.checkContainsJSON = void 0;
const parseJSON_1 = require("../../../../../../../utils/json/parseJSON");
const UnexpectedCodePathError_1 = require("../../../../../../UnexpectedCodePathError");
const check_minVersion_1 = require("../../checkExpressions/check.minVersion");
const checkContainsSubstring_1 = require("./checkContainsSubstring");
/**
* the function that evaluates the "min version" json check expressions
*
* e.g., `@declapract{check.minVersion('4.0.0')}` => apply the regexp checking min version of '4.0.0'
*/
const evaluateSupportedJSONCheckExpressionMinimumVersion = ({ declaredValue, foundValue, }) => {
// grab the min version expected from the declared value check expression
const minVersion = (0, check_minVersion_1.getMinVersionFromCheckMinVersionExpression)(declaredValue);
if (!minVersion)
throw new UnexpectedCodePathError_1.UnexpectedCodePathError('JSONCheckExpressionMinimumVersion attempted to be evaluated, but no minVersion could be declared from check expression declaration', { declaredValue });
// check whether it passes
const passesMinVersionCheck = (0, check_minVersion_1.checkDoesFoundValuePassesMinVersionCheck)({
foundValue,
minVersion,
});
// if foundValue does not match it, return the error message
if (!passesMinVersionCheck)
return `a version greater than or equal to '${minVersion}'`;
// if it does match it, then return the value we found (so that there's no diff due to this one)
return foundValue;
};
/**
* a function which recursively evaluates the declaredContents.
*
* returns:
* - the declared value, if not a supported check expression
* - the found value, if successfully evaluated against the check expression
* - an error string, if failed evaluating against a check expression
*
* why?: in order to evaluate each of the check expressions we support and display them in an easy to read diff
*/
const recursivelyEvaluateDeclaredContentsToCheckContains = ({ declared, found, }) => {
// sanity check that there's anything to do
if (!declared || typeof declared !== 'object')
return declared; // nothing to eval, if declared is not an object
if (!found || typeof found !== 'object')
return declared; // nothing to eval, if found is not an object
// start tracking the object that we'll record evaluated values in
const declaredToCheckContains = {};
// evaluate each key one at a time, to preserve order
const keysToEvaluate = Object.keys(declared);
for (const key of keysToEvaluate) {
const declaredValue = declared[key];
const foundValue = found[key];
// evaluate the value; replace if needed
const evaluatedValue = (() => {
// handle case where declared value is falsy
if (!declaredValue)
return declaredValue;
// handle cases where the declared value is itself an object (i.e., go one layer deeper, recursively)
if (typeof declaredValue === 'object')
return recursivelyEvaluateDeclaredContentsToCheckContains({
declared: declaredValue,
found: foundValue,
});
// handle cases where the declared value is a check reference to evaluate
if (typeof declaredValue === 'string' &&
declaredValue.startsWith('@declapract{check.')) {
if ((0, check_minVersion_1.isCheckMinVersionExpression)(declaredValue)) {
const evaluatedValue = evaluateSupportedJSONCheckExpressionMinimumVersion({
declaredValue,
foundValue,
});
return evaluatedValue;
}
}
// if did not match any of the above, then its just the declared value still
return declaredValue;
})();
// set the evaluated value in the declaredToCheckContains object
declaredToCheckContains[key] = evaluatedValue;
}
// return the declared to check contains object
return declaredToCheckContains;
};
/**
* a function which recursively filters down the found contents to the ones that were specified as relevant by the declared contents.
*/
const recursivelyFilterFoundContentsToCheckContains = ({ declared, found, }) => {
// sanity check that there's anything to do
if (!declared || typeof declared !== 'object')
return {}; // nothing to compare against, if declared is not an object
if (!found || typeof found !== 'object')
return found; // nothing to filter, if found is not an object
// start tracking the object that we'll record evaluated values in
const foundToCheckContains = {};
// evaluate each key one at a time, to preserve order
const keysToFilter = Object.keys(declared);
for (const key of keysToFilter) {
const declaredValue = declared[key];
const foundValue = found[key];
// evaluate the value; replace if needed
const filteredValue = (() => {
// handle case where declared value is falsy
if (!declaredValue)
return foundValue;
// handle cases where the declared value is itself an object (i.e., go one layer deeper, recursively)
if (typeof declaredValue === 'object')
return recursivelyFilterFoundContentsToCheckContains({
declared: declaredValue,
found: foundValue,
});
// if did not match any of the above, then its just the declared value still
return foundValue;
})();
// set the evaluated value in the declaredToCheckContains object
foundToCheckContains[key] = filteredValue;
}
// return the declared to check contains object
return foundToCheckContains;
};
const checkContainsJSON = ({ declaredContents, foundContents, }) => {
// json parse the contents
const parsedDeclaredContents = (0, parseJSON_1.parseJSON)(declaredContents);
const parsedFoundContents = (0, parseJSON_1.parseJSON)(foundContents);
// define the "declaredContentsToCheckContains" and "foundContentsToCheckContains" by evaluating any "@declapract{check.}" expressions and excluding any irrelevant keys, recursively
const declaredContentsToCheckContains = recursivelyEvaluateDeclaredContentsToCheckContains({
declared: parsedDeclaredContents,
found: parsedFoundContents,
});
const foundContentsToCheckContains = recursivelyFilterFoundContentsToCheckContains({
declared: parsedDeclaredContents,
found: parsedFoundContents,
});
// and do the contains substring check on those two strings now, to show diff better
(0, checkContainsSubstring_1.checkContainsSubstring)({
declaredContents: JSON.stringify(declaredContentsToCheckContains, null, 2),
foundContents: JSON.stringify(foundContentsToCheckContains, null, 2),
bAnnotation: 'Received relevantKeys',
});
};
exports.checkContainsJSON = checkContainsJSON;
//# sourceMappingURL=checkContainsJSON.js.map