core/factories/diagram.factory.ts
core/factories/diagram.factory.ts is a file in GovLab Docs. 55 lines of code and 16 definitions.
import type { DiagramContext, PackageShape } from "#types/figure.types";
import { LAYOUT_BY_SHAPE } from "#configuration/constants/figure.constants";
import type { ModuleDep } from "#types/diagram.types";
import { PACKAGE_FILE } from "#configuration/constants/document.constants";
import { deriveCodeGraph } from "#core/coordinators/code.coordinator";
import { deriveTypeGraph } from "#core/analyzers/definition.analyzer";
import { isPlainRecord } from "#core/predicates/record.predicate";
import { readJsonSafe } from "#core/loaders/base.loader";
import { resolve } from "node:path";
import { scopedDepNames } from "#core/converters/dependency.converter";
import { shapeOf } from "#core/classifiers/package.classifier";
export const loadPackage = function loadPackage(moduleDir: string): Record<string, unknown> {
const parsed = readJsonSafe(resolve(moduleDir, PACKAGE_FILE));
return isPlainRecord(parsed) ? parsed : {};
};
export const packageName = function packageName(pkg: Record<string, unknown>, fallback: string): string {
const { name } = pkg;
return typeof name === "string" ? name : fallback;
};
export const scriptsOf = function scriptsOf(pkg: Record<string, unknown>): { scripts?: Record<string, string> } {
const declared = pkg["scripts"];
const entries = Object.entries(isPlainRecord(declared) ? declared : {}).filter(
(entry): entry is [string, string] => typeof entry[1] === "string",
);
return entries.length > 0 ? { scripts: Object.fromEntries(entries) } : {};
};
export const shapedContext = function shapedContext(shape: PackageShape): Pick<DiagramContext, "layout" | "shape"> {
return { layout: LAYOUT_BY_SHAPE[shape], shape };
};
const moduleDepsFor = function moduleDepsFor(pkg: Record<string, unknown>, name: string): ModuleDep[] {
const deps = scopedDepNames(pkg["dependencies"]);
return [{ deps, name }, ...deps.map((dep) => ({ deps: [], name: dep }))];
};
export const diagramContextFor = async function diagramContextFor(
moduleDir: string,
relPath: string,
label?: string,
): Promise<DiagramContext | null> {
const pkg = loadPackage(moduleDir);
const name = label ?? packageName(pkg, relPath);
const codeGraph = await deriveCodeGraph(moduleDir, pkg);
const typeGraph = deriveTypeGraph(moduleDir, pkg);
const scripts = scriptsOf(pkg);
if (codeGraph === null && typeGraph.edges.length === 0 && scripts.scripts === undefined) {
return null;
}
return {
codeGraph,
moduleDeps: moduleDepsFor(pkg, name),
moduleName: name,
typeGraph,
...shapedContext(shapeOf(moduleDir, pkg)),
...scripts,
};
};