core/loaders/quality.loader.ts

core/loaders/quality.loader.ts is a file in GovLab Quality. 137 lines of code and 29 definitions.

import type {
    Exemplar,
    QualityConcept,
    QualityConcernRecord,
    QualityData,
    QualityRuleRecord,
    QualityToolRecord,
    ToolKnob,
} from "#types/catalog.types";
import { existsSync, readFileSync, readdirSync } from "node:fs";
import { isRecord, numberField, recordsAt, stringArrayField, stringField } from "#core/selectors/record.selector";
import { absolutePath } from "@ssot/paths";
import { jsonRecord } from "#core/parsers/record.parser";
import path from "node:path";

const CONCERNS_FILE = "concerns.generated.json";
const TOOLS_FILE = "tools.generated.json";
const GENERATED_JSON = ".generated.json";
const DEFAULT_EXEMPLAR_LANG = "ts";

const readRecords = function readRecords(file: string): Record<string, unknown>[] {
    return recordsAt(jsonRecord(readFileSync(file, "utf8")), "records");
};

const asExemplar = function asExemplar(value: unknown): Exemplar | null {
    if (!isRecord(value)) {
        return null;
    }
    const before = stringField(value, "before");
    const after = stringField(value, "after");
    if (before.length === 0 && after.length === 0) {
        return null;
    }
    return { after, before, lang: stringField(value, "lang") || DEFAULT_EXEMPLAR_LANG };
};

const toConcept = function toConcept(raw: Record<string, unknown>): QualityConcept | null {
    const concept: QualityConcept = {
        dimension: stringField(raw, "dimension"),
        id: stringField(raw, "id"),
        total: numberField(raw, "total", 0),
    };
    const exemplar = asExemplar(raw["exemplar"]);
    if (exemplar !== null) {
        concept.exemplar = exemplar;
    }
    return concept.id ? concept : null;
};

const loadConcepts = function loadConcepts(): QualityConcept[] {
    const file = absolutePath("govlab.quality.generated.concepts");
    if (!existsSync(file)) {
        return [];
    }
    return recordsAt(jsonRecord(readFileSync(file, "utf8")), "concepts")
        .map(toConcept)
        .filter((concept): concept is QualityConcept => concept !== null);
};

const asScalar = function asScalar(value: unknown): boolean | number | string | null {
    return typeof value === "number" || typeof value === "string" || typeof value === "boolean" ? value : null;
};

const asStringRecord = function asStringRecord(value: Record<string, unknown>): Record<string, string> {
    return Object.fromEntries(
        Object.entries(value).filter((entry): entry is [string, string] => typeof entry[1] === "string"),
    );
};

const normKnob = function normKnob(raw: Record<string, unknown>): ToolKnob {
    return {
        default: asScalar(raw["default"]),
        knob: stringField(raw, "knob"),
        threshold: raw["threshold"] === true,
        type: stringField(raw, "type"),
    };
};

const normConcern = function normConcern(raw: Record<string, unknown>): QualityConcernRecord {
    const declared = raw["value"];
    const value = typeof declared === "number" || typeof declared === "boolean" ? declared : true;
    const concern: QualityConcernRecord = {
        name: stringField(raw, "name"),
        numeric: typeof value === "number",
        ruleCount: numberField(raw, "ruleCount", 0),
        severity: stringField(raw, "severity") || "error",
        toolCount: numberField(raw, "toolCount", 0),
        value,
    };
    const { configOptions, knobPerTool, valueDerivation } = raw;
    if (typeof valueDerivation === "string") {
        concern.valueDerivation = valueDerivation;
    }
    if (isRecord(knobPerTool)) {
        concern.knobPerTool = asStringRecord(knobPerTool);
    }
    if (Array.isArray(configOptions)) {
        concern.configOptions = stringArrayField(raw, "configOptions");
    }
    return concern;
};

const normRule = function normRule(raw: Record<string, unknown>): QualityRuleRecord {
    const rule: QualityRuleRecord = {
        category: stringField(raw, "category"),
        concern: stringField(raw, "concern"),
        ecosystem: stringField(raw, "ecosystem"),
        name: stringField(raw, "name"),
        ruleId: stringField(raw, "ruleId"),
        ruleName: stringField(raw, "ruleName"),
        tool: stringField(raw, "tool"),
        url: stringField(raw, "url"),
    };
    const canonical = stringArrayField(raw, "canonical");
    if (canonical.length > 0) {
        rule.canonical = canonical;
    }
    const knobs = recordsAt(raw, "knobs");
    if (knobs.length > 0) {
        rule.knobs = knobs.map(normKnob);
    }
    return rule;
};

const normTool = function normTool(raw: Record<string, unknown>): QualityToolRecord {
    return {
        detectionOnly: raw["detectionOnly"] === true,
        ecosystem: stringField(raw, "ecosystem"),
        knobCount: numberField(raw, "knobCount", 0),
        name: stringField(raw, "name"),
        ruleCount: numberField(raw, "ruleCount", 0),
    };
};

const loadRules = function loadRules(): QualityRuleRecord[] {
    const dir = absolutePath("govlab.quality.ecosystemRules");
    return readdirSync(dir)
        .filter((name) => name.endsWith(GENERATED_JSON))
        .toSorted((a, b) => a.localeCompare(b))
        .flatMap((name) => readRecords(path.join(dir, name)).map(normRule));
};

export const loadQualityData = function loadQualityData(): QualityData {
    return {
        concepts: loadConcepts(),
        concerns: readRecords(absolutePath("govlab.quality.generated", CONCERNS_FILE)).map(normConcern),
        rules: loadRules(),
        tools: readRecords(absolutePath("govlab.quality.generated", TOOLS_FILE)).map(normTool),
    };
};