declapract
Version:
A tool to declaratively define best practices, maintainable evolve them, and scalably enforce them.
124 lines • 6.95 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.evaluateProjectAgainstFileCheckDeclaration = void 0;
const fast_glob_1 = __importDefault(require("fast-glob"));
const domain_1 = require("../../../domain");
const FileCheckContext_1 = require("../../../domain/objects/FileCheckContext");
const readFileIfExistsAsync_1 = require("../../../utils/fileio/readFileIfExistsAsync");
const withDurationReporting_1 = require("../../../utils/wrappers/withDurationReporting");
const UnexpectedCodePathError_1 = require("../../UnexpectedCodePathError");
const replaceProjectVariablesInDeclaredFileContents_1 = require("./projectVariableExpressions/replaceProjectVariablesInDeclaredFileContents");
const checkApplyingFixWouldChangeSomething = ({ fixResults, foundContents, context, }) => {
// determine whether user declared a new value for each option - or whether they omitted them
const declaredNewContents = fixResults.contents !== undefined;
const declaredNewPath = fixResults.relativeFilePath !== undefined;
// now determine whether they changed anything with what they declared
if (declaredNewContents && fixResults.contents !== foundContents)
return true; // if they declared new contents - and the contents are different than what they are now - then changed
if (declaredNewPath &&
fixResults.relativeFilePath !== context.relativeFilePath)
return true; // if they declared a path - and the path is different than what it is now - then changed
return false; // otherwise, no change
};
const evaluateProjectAgainstFileCheckDeclaration = async ({ practiceRef, purpose, project, check, }) => {
// lookup the gitignore file for the directory
// define the absolute file paths to check, dereferencing the check.path glob pattern
const pathsFoundByGlob = await (0, withDurationReporting_1.withDurationReporting)(`glob:${check.pathGlob}`, () => (0, fast_glob_1.default)(check.pathGlob, {
cwd: project.getProjectRootDirectory(), // relative to project root,
dot: true, // include dot files,
onlyFiles: true, // only files, no directories (these are file checks, directories are not files)
ignore: ['node_modules'], // ignore all files in these specific directories, too
}))();
const pathsToCheck = pathsFoundByGlob.length
? pathsFoundByGlob
: [check.pathGlob]; // if no paths found for the glob pattern, then just use the glob pattern and check against it (i.e., run the "exists" checks against that path)
// for each file found by the glob pattern, evaluate it
return await Promise.all(pathsToCheck.map(async (relativePath) => {
// define the absolute file path
const filePath = `${project.getProjectRootDirectory()}/${relativePath}`;
// grab the contents of the file
const foundContents = await (0, readFileIfExistsAsync_1.readFileIfExistsAsync)({ filePath });
// define the context of this file check
const context = new FileCheckContext_1.FileCheckContext({
...project,
relativeFilePath: relativePath,
declaredFileContents: check.contents
? (0, replaceProjectVariablesInDeclaredFileContents_1.replaceProjectVariablesInDeclaredFileContents)({
projectVariables: project.projectVariables,
fileContents: await check.contents(project),
})
: null,
required: check.required,
});
// check the file contents against declared check
try {
// run the check
await check.check(foundContents, context);
// determine the result of the check based on the context
const result = (() => {
if (purpose === domain_1.FileCheckPurpose.BEST_PRACTICE)
return domain_1.FileEvaluationResult.PASS;
if (purpose === domain_1.FileCheckPurpose.BAD_PRACTICE)
return domain_1.FileEvaluationResult.FAIL; // if it matches a bad practice, then it failed the check
throw new UnexpectedCodePathError_1.UnexpectedCodePathError('context was not best practice or bad practice');
})();
// determine whether can fix, if failed
const canFix = result === domain_1.FileEvaluationResult.FAIL &&
// fixable only if fix fn is defined and it would have changed something
check.fix &&
checkApplyingFixWouldChangeSomething({
fixResults: await check.fix(foundContents, context),
foundContents,
context,
});
// build the evaluation
return new domain_1.FileCheckEvaluation({
practiceRef,
purpose,
type: check.type,
required: check.required,
fix: canFix ? check.fix : null,
path: relativePath,
result,
reason: null,
context,
});
}
catch (error) {
// determine the result of the check based on the context
const result = (() => {
if (purpose === domain_1.FileCheckPurpose.BEST_PRACTICE)
return domain_1.FileEvaluationResult.FAIL;
if (purpose === domain_1.FileCheckPurpose.BAD_PRACTICE)
return domain_1.FileEvaluationResult.PASS; // if it throws an error (i.e., does not match) a bad practice, then it passes the check
throw new UnexpectedCodePathError_1.UnexpectedCodePathError('context was not bet practice or bad practice');
})();
// determine whether can fix, if failed
const canFix = result === domain_1.FileEvaluationResult.FAIL &&
// fixable only if fix fn is defined and it would have changed something
check.fix &&
checkApplyingFixWouldChangeSomething({
fixResults: await check.fix(foundContents, context),
foundContents,
context,
});
// build the evaluation
return new domain_1.FileCheckEvaluation({
practiceRef,
purpose,
type: check.type,
required: check.required,
fix: canFix ? check.fix : null,
path: relativePath,
result,
reason: error.message,
context,
});
}
}));
};
exports.evaluateProjectAgainstFileCheckDeclaration = evaluateProjectAgainstFileCheckDeclaration;
//# sourceMappingURL=evaluateProjectAgainstFileCheckDeclaration.js.map