declapract
Version:
A tool to declaratively define best practices, maintainable evolve them, and scalably enforce them.
128 lines • 7.68 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
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 = (_a) => __awaiter(void 0, [_a], void 0, function* ({ 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 = yield (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 yield Promise.all(pathsToCheck.map((relativePath) => __awaiter(void 0, void 0, void 0, function* () {
// define the absolute file path
const filePath = `${project.getProjectRootDirectory()}/${relativePath}`;
// grab the contents of the file
const foundContents = yield (0, readFileIfExistsAsync_1.readFileIfExistsAsync)({ filePath });
// define the context of this file check
const context = new FileCheckContext_1.FileCheckContext(Object.assign(Object.assign({}, project), { relativeFilePath: relativePath, declaredFileContents: check.contents
? (0, replaceProjectVariablesInDeclaredFileContents_1.replaceProjectVariablesInDeclaredFileContents)({
projectVariables: project.projectVariables,
fileContents: yield check.contents(project),
})
: null, required: check.required }));
// check the file contents against declared check
try {
// run the check
yield 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: yield 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: yield 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
;