core/coordinators/validation.coordinator.ts

core/coordinators/validation.coordinator.ts is a file in GovLab Quality. 60 lines of code and 10 definitions.

import type {
    FileInput,
    FileReader,
    ProjectValidator,
    ValidationInput,
    ValidationResult,
} from "#types/validation.types";
import type { Finding } from "#types/finding.types";
import { VALIDATOR_SUFFIX } from "#configuration/constants/validation.constants";
import { importFolder } from "#core/loaders/folder.loader";
import { isNotFound } from "#core/predicates/failure.predicate";
import { registeredValidators } from "#core/registries/validation.registry";
import { renderPanel } from "#core/formatters/validation.formatter";

const extensionOf = function extensionOf(path: string): string {
    const dotIdx = path.lastIndexOf(".");
    return dotIdx === -1 ? "" : path.slice(dotIdx + 1);
};

const safeRead = function safeRead(readFile: FileReader, path: string): string | null {
    try {
        return readFile(path);
    } catch (error) {
        if (error instanceof Error && isNotFound(error)) {
            return null;
        }
        throw error;
    }
};

const readInputs = function readInputs(readFile: FileReader, files: readonly string[]): FileInput[] {
    return files.flatMap((path) => {
        const content = safeRead(readFile, path);
        return content === null ? [] : [{ content, path }];
    });
};

const applies = function applies(validator: ProjectValidator, entry: FileInput): boolean {
    return validator.appliesTo === "*" || validator.appliesTo.includes(extensionOf(entry.path));
};

const validatorFindings = function validatorFindings(
    validators: readonly ProjectValidator[],
    inputs: readonly FileInput[],
    consumers: readonly FileInput[],
): Finding[] {
    return validators.flatMap((validator) =>
        validator.validate(
            inputs.filter((entry) => applies(validator, entry)),
            consumers.filter((entry) => applies(validator, entry)),
        ),
    );
};

export const loadValidators = async function loadValidators(): Promise<ProjectValidator[]> {
    await importFolder("govlab.quality.validators", VALIDATOR_SUFFIX);
    return registeredValidators();
};

export const runValidators = function runValidators(input: ValidationInput): ValidationResult {
    const findings = validatorFindings(
        input.validators,
        readInputs(input.readFile, input.files),
        readInputs(input.readFile, input.consumers),
    );
    return { clean: findings.length === 0, findings, panel: renderPanel(findings) };
};