core/validators/architecture.validator.ts

core/validators/architecture.validator.ts is a file in GovLab Context. 48 lines of code and 7 definitions.

import { CONDITIONAL_SEVERITY, NEGATIVE_KIND } from "#configuration/constants/architecture.constants";
import type { ArchRelations } from "#types/architecture.types";
import type { InvalidSeverity } from "#types/validation.types";
import type { Lexicon } from "#types/lexicon.types";
import { PAG_PREFIX } from "#configuration/constants/reference.constants";
import type { TargetResolverFaces } from "#types/reference.types";
import { conditionalSeverityNeeded } from "#configuration/strings/validation.strings";
import { resolveTarget } from "#core/resolvers/reference.resolver";
import { slugify } from "#core/converters/identifier.converter";

type ExpressionFaces = TargetResolverFaces & { arch: { all: () => { expressedBy?: readonly string[]; id: string }[] } };

export const unresolvedExpressionsOf = function unresolvedExpressionsOf(
    faces: ExpressionFaces,
): { from: string; target: string }[] {
    return faces.arch
        .all()
        .flatMap((principle) =>
            (principle.expressedBy ?? [])
                .filter((target) => !target.startsWith(PAG_PREFIX) || !resolveTarget(faces, target))
                .map((target) => ({ from: principle.id, target })),
        );
};

export const unreachableAntiPatternsOf = function unreachableAntiPatternsOf(arch: ArchRelations): string[] {
    const conflictsTargets = new Set(
        arch
            .all()
            .flatMap((principle) => principle.conflicts_with)
            .map((target) => slugify(target)),
    );
    return arch
        .all()
        .filter((principle) => principle.type === NEGATIVE_KIND)
        .filter(
            (principle) =>
                !conflictsTargets.has(slugify(principle.id)) && !conflictsTargets.has(slugify(principle.name)),
        )
        .map((principle) => principle.id)
        .toSorted((a, b) => a.localeCompare(b));
};

export const crossFaceCollisions = function crossFaceCollisions(arch: ArchRelations, lex: Lexicon): string[] {
    const archIdSet = new Set(arch.ids());
    return lex.ids().filter((id) => archIdSet.has(id));
};

export const invalidSeveritiesOf = function invalidSeveritiesOf(arch: ArchRelations): InvalidSeverity[] {
    return arch
        .all()
        .filter((principle) => principle.mandatoryFor !== undefined && principle.severity !== CONDITIONAL_SEVERITY)
        .map((principle) => ({ id: principle.id, reason: conditionalSeverityNeeded(CONDITIONAL_SEVERITY) }));
};