core/factories/document.factory.ts

core/factories/document.factory.ts is a file in GovLab Docs. 96 lines of code and 18 definitions.

import type {
    ArchPort,
    ConceptRecord,
    ContextDeps,
    Manifest,
    ModuleDocs,
    ModuleDocsOptions,
    PrincipleRecord,
    RenderContext,
    RepoMetrics,
} from "#types/readme.types";
import type { DocRegistries, LocationOptions } from "#types/location.types";
import { basename, resolve } from "node:path";
import { governConcepts, governPrinciples, ontologyDuplicateFindings } from "#core/validators/governance.validator";
import { governDeclaredDocs, governManifest } from "#core/validators/manifest.prose.validator";
import { readManifest, readPackageJson } from "#core/loaders/manifest.loader";
import { DEFAULT_ROOT_PREFIX } from "#configuration/constants/document.constants";
import { DOC_FORMS } from "#configuration/constants/form.constants";
import { PACKAGE_SCOPE } from "#configuration/constants/manifest.constants";
import { VCS_DIRECTORY } from "#configuration/constants/vcs.constants";
import { declaredDocLocation } from "#core/resolvers/location.resolver";
import { existsSync } from "node:fs";
import { generateModuleDoc } from "#core/formatters/readme.formatter";
import { readPublicSurface } from "#core/analyzers/surface.analyzer";
import { renderDeclaredDoc } from "#core/formatters/document.formatter";

const REPO_METRICS_KEY = "repoMetrics";

const resolvePrinciples = function resolvePrinciples(manifest: Manifest, archRelations: ArchPort): PrincipleRecord[] {
    const ids = manifest.governance?.principles;
    return Array.isArray(ids) && ids.length > 0 ? archRelations.resolve(ids).principles : [];
};

const resolveConcepts = function resolveConcepts(manifest: Manifest, slug: string, deps: ContextDeps): ConceptRecord[] {
    const declared = Array.isArray(manifest.governedBy) && manifest.governedBy.length > 0 ? manifest.governedBy : null;
    const ids = declared ?? deps.deriveGovernedBy(slug) ?? [];
    return ids.flatMap((id) => {
        const concept = deps.conceptMap.get(id);
        return concept === undefined ? [] : [{ dimension: concept.dimension, id: concept.id }];
    });
};

const repoMetricsFor = function repoMetricsFor(
    manifest: Manifest,
    moduleDir: string,
    deps: ContextDeps,
): RepoMetrics | null {
    const derive = deps.deriveRepoMetrics;
    if (derive === undefined || manifest[REPO_METRICS_KEY] !== true || !existsSync(resolve(moduleDir, VCS_DIRECTORY))) {
        return null;
    }
    return derive(moduleDir);
};

const buildContext = function buildContext(moduleDir: string, hasCharts: boolean, deps: ContextDeps): RenderContext {
    const manifest = readManifest(moduleDir);
    const pkg = readPackageJson(moduleDir);
    const name = basename(moduleDir);
    return {
        concepts: resolveConcepts(manifest, name, deps),
        docs: manifest.docs ?? {},
        domains: Array.isArray(manifest.domains) ? manifest.domains : [],
        hasCharts,
        maturity: typeof manifest["maturity"] === "string" ? manifest["maturity"] : "",
        moduleDir,
        name,
        pkg,
        principles: resolvePrinciples(manifest, deps.archRelations),
        repo: repoMetricsFor(manifest, moduleDir, deps),
        scoped: pkg.name ?? manifest.label ?? `${PACKAGE_SCOPE}${name}`,
        summary: manifest.summary ?? "",
        surface: readPublicSurface(moduleDir, pkg).surface,
    };
};

export const createModuleDocs = function createModuleDocs(options: ModuleDocsOptions): ModuleDocs {
    const { archRelations, conceptMap, consumerRoot, hostTokens } = options;
    const registries: DocRegistries = {
        concerns: options.docConcerns,
        forms: options.docForms ?? DOC_FORMS,
        owners: options.docMembers,
    };
    const locationOptions: LocationOptions = { rootPrefix: DEFAULT_ROOT_PREFIX };
    const declaredContext = { consumerRoot, hostTokens, options: locationOptions, registries };
    const contextDeps: ContextDeps = {
        archRelations,
        conceptMap,
        deriveGovernedBy: options.deriveGovernedBy,
        deriveRepoMetrics: options.deriveRepoMetrics,
    };
    return {
        declaredDocLocation: (doc) => declaredDocLocation(doc, registries, locationOptions),
        generateReadme: (moduleDir, hasCharts = false) =>
            generateModuleDoc(buildContext(moduleDir, hasCharts, contextDeps)),
        governConcepts: (manifest) => governConcepts(manifest, conceptMap),
        governDeclaredDocs: (module) => governDeclaredDocs(module, declaredContext),
        governManifest: (module) => governManifest(module, consumerRoot, hostTokens),
        governPrinciples: (manifest) => governPrinciples(manifest, archRelations),
        ontologyDuplicates: () => ontologyDuplicateFindings(archRelations),
        renderDeclaredDoc,
    };
};