core/resolvers/package.resolver.ts

core/resolvers/package.resolver.ts is a file in GovLab Stats. 43 lines of code and 12 definitions.

import { PACKAGE_MANIFEST, WILDCARD, WORKSPACES_KEY } from "#configuration/constants/package.constants";
import { arrayField, stringsIn } from "#core/selectors/field.selector";
import path from "node:path";
import { posixOf } from "#core/selectors/source.selector";
import { readJson } from "#core/loaders/data.loader";
import { readdirSafe } from "#core/loaders/folder.loader";

const matchesSegment = function matchesSegment(pattern: string, name: string): boolean {
    if (!pattern.includes(WILDCARD)) {
        return pattern === name;
    }
    const [head = "", tail = ""] = pattern.split(WILDCARD);
    return name.startsWith(head) && name.endsWith(tail) && name.length >= head.length + tail.length;
};

const expand = function expand(absDir: string, segments: readonly string[]): string[] {
    const [head, ...rest] = segments;
    if (head === undefined) {
        return [absDir];
    }
    if (!head.includes(WILDCARD)) {
        return expand(path.join(absDir, head), rest);
    }
    return readdirSafe(absDir)
        .filter((entry) => entry.isDirectory() && matchesSegment(head, entry.name))
        .flatMap((entry) => expand(path.join(absDir, entry.name), rest));
};

const holdsManifest = function holdsManifest(abs: string): boolean {
    return readdirSafe(abs).some((entry) => entry.isFile() && entry.name === PACKAGE_MANIFEST);
};

export const workspaceMembers = function workspaceMembers(root: string): string[] {
    const manifest = readJson(path.join(root, PACKAGE_MANIFEST));
    const patterns = stringsIn(arrayField(manifest, WORKSPACES_KEY));
    const candidates = patterns.flatMap((pattern) => expand(root, pattern.split("/")));
    return [...new Set(candidates.filter(holdsManifest))].toSorted((a, b) => a.localeCompare(b));
};

export const memberIndex = function memberIndex(root: string): string[] {
    return workspaceMembers(root)
        .map((abs) => posixOf(path.relative(root, abs)))
        .toSorted((a, b) => b.length - a.length);
};

export const ownerOf = function ownerOf(members: readonly string[], relPath: string): string | null {
    const norm = posixOf(relPath);
    return members.find((member) => norm === member || norm.startsWith(`${member}/`)) ?? null;
};