UNPKG

declapract

Version:

A tool to declaratively define best practices, maintainable evolve them, and scalably enforce them.

128 lines 7.68 kB
"use strict"; 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