core/loaders/config.loader.ts

core/loaders/config.loader.ts is a file in GovLab Quality. 103 lines of code and 27 definitions.

import "#core/schemas/config.schema";
import "#core/schemas/eslint.schema";
import "#core/schemas/tool.schema";
import { basename, dirname, resolve } from "node:path";
import type { GovlabConfig } from "#types/config.types";
import { configInvalid } from "#configuration/strings/quality.strings";
import { createJiti } from "jiti";
import { existsSync } from "node:fs";
import { pathToFileURL } from "node:url";
import { relativePath } from "@ssot/paths";
import { validateConfig } from "#core/registries/section.registry";

const CONFIG_BASENAMES = [
    relativePath("govlabHost.config"),
    "govlab.config.mts",
    "govlab.config.cts",
    "govlab.config.js",
    "govlab.config.mjs",
];

const CONFIG_DIRS = [".", "config", relativePath("govlabHost.root")];
const DEPENDENCY_FOLDER = "node_modules";
const EXTENDS_KEY = "extends";

const CONFIG_CACHE = new Map<string, Promise<GovlabConfig>>();

const isObject = function isObject(value: unknown): value is Record<string, unknown> {
    return value !== null && typeof value === "object" && !Array.isArray(value);
};

const deepMerge = function deepMerge(
    base: Record<string, unknown>,
    override: Record<string, unknown>,
): Record<string, unknown> {
    const out: Record<string, unknown> = { ...base };
    for (const [key, value] of Object.entries(override)) {
        const prev = out[key];
        out[key] = isObject(prev) && isObject(value) ? deepMerge(prev, value) : value;
    }
    return out;
};

const withoutExtends = function withoutExtends(config: GovlabConfig): Record<string, unknown> {
    return Object.fromEntries(Object.entries(config).filter(([key]) => key !== EXTENDS_KEY));
};

const mergeExtends = function mergeExtends(config: GovlabConfig): GovlabConfig {
    const bases = Array.isArray(config.extends) ? config.extends : [];
    if (bases.length === 0) {
        return config;
    }
    let merged: Record<string, unknown> = {};
    for (const base of bases) {
        merged = deepMerge(merged, mergeExtends(base));
    }
    return deepMerge(merged, withoutExtends(config));
};

export const resolveConfigInDir = function resolveConfigInDir(dir: string): string | null {
    for (const sub of CONFIG_DIRS) {
        for (const base of CONFIG_BASENAMES) {
            const file = resolve(dir, sub, base);
            if (existsSync(file)) {
                return file;
            }
        }
    }
    return null;
};

const firstExistingConfig = function firstExistingConfig(root: string): string | null {
    let dir = resolve(root);
    for (;;) {
        if (basename(dir) !== DEPENDENCY_FOLDER) {
            const hit = resolveConfigInDir(dir);
            if (hit !== null) {
                return hit;
            }
        }
        const parent = dirname(dir);
        if (parent === dir) {
            return null;
        }
        dir = parent;
    }
};

const importConfig = async function importConfig(file: string): Promise<GovlabConfig> {
    const jiti = createJiti(pathToFileURL(file).href, { fsCache: false });
    const loaded = await jiti.import(file, { default: true });
    return isObject(loaded) ? loaded : {};
};

const readConfig = async function readConfig(file: string): Promise<GovlabConfig> {
    const merged = mergeExtends(await importConfig(file));
    const errors = validateConfig(merged);
    if (errors.length > 0) {
        throw new Error(configInvalid(file, errors.join(", ")));
    }
    return merged;
};

export const loadGovlabConfig = async function loadGovlabConfig(root: string): Promise<GovlabConfig> {
    const file = firstExistingConfig(root);
    if (file === null) {
        return {};
    }
    const cached = CONFIG_CACHE.get(file);
    if (cached !== undefined) {
        return cached;
    }
    const pending = readConfig(file);
    CONFIG_CACHE.set(file, pending);
    return pending;
};