# core/loaders/source.loader.ts

> 54 lines of code and 12 definitions.

Tree: GovLab Quality
Language: typescript
Layer: infrastructure
Canonical: https://banes-lab.com/anatomy/quality#file-quality-core-loaders-source-loader-ts
Source text: https://banes-lab.com/source/quality/core/loaders/source.loader.ts.txt

Listed in [core/loaders](https://banes-lab.com/api/source/quality/core/loaders.md), after [core/loaders/rule.loader.ts](https://banes-lab.com/source/quality/core/loaders/rule.loader.ts.md) and before [core/loaders/tool.loader.ts](https://banes-lab.com/source/quality/core/loaders/tool.loader.ts.md).

## Definitions

- `safeReaddir` (lexical_declaration, line 20, exported)
- `missingOr` (lexical_declaration, line 5)
- `safeStat` (lexical_declaration, line 28, exported)
- `isRecord` (lexical_declaration, line 36)
- `readFileSafe` (lexical_declaration, line 12, exported)
- `readJsonField` (lexical_declaration, line 45, exported)
- `walkFiles` (lexical_declaration, line 50, exported)
- `readJsonFile` (lexical_declaration, line 40, exported)
- `text` (lexical_declaration, line 41, exported)
- `parsed` (lexical_declaration, line 46, exported)
- `full` (lexical_declaration, line 52, exported)
- `stat` (lexical_declaration, line 53, exported)

## Contained in

- [core/loaders](https://banes-lab.com/anatomy/quality/folder-quality-core-loaders.md)

## Uses

- [core/predicates/failure.predicate.ts](https://banes-lab.com/source/quality/core/predicates/failure.predicate.ts.md)

## Used by

- [core/adapters/tool.htmlhint.adapter.ts](https://banes-lab.com/source/quality/core/adapters/tool.htmlhint.adapter.ts.md)
- [core/adapters/tool.knip.adapter.ts](https://banes-lab.com/source/quality/core/adapters/tool.knip.adapter.ts.md)
- [core/loaders/comment.loader.ts](https://banes-lab.com/source/quality/core/loaders/comment.loader.ts.md)
- [core/loaders/coverage.loader.ts](https://banes-lab.com/source/quality/core/loaders/coverage.loader.ts.md)
- [core/loaders/package.loader.ts](https://banes-lab.com/source/quality/core/loaders/package.loader.ts.md)
- [core/resolvers/scope.resolver.ts](https://banes-lab.com/source/quality/core/resolvers/scope.resolver.ts.md)
- [core/visitors/block.visitor.ts](https://banes-lab.com/source/quality/core/visitors/block.visitor.ts.md)
- [runtime/entrypoints/validation.entrypoint.ts](https://banes-lab.com/source/quality/runtime/entrypoints/validation.entrypoint.ts.md)

## Linked from

- [core/adapters](https://banes-lab.com/anatomy/quality/folder-quality-core-adapters.md)
- [core/loaders](https://banes-lab.com/anatomy/quality/folder-quality-core-loaders.md)
- [core/predicates](https://banes-lab.com/anatomy/quality/folder-quality-core-predicates.md)
- [core/resolvers](https://banes-lab.com/anatomy/quality/folder-quality-core-resolvers.md)
- [core/visitors](https://banes-lab.com/anatomy/quality/folder-quality-core-visitors.md)
- [runtime/entrypoints](https://banes-lab.com/anatomy/quality/folder-quality-runtime-entrypoints.md)

## Source

```typescript
import fs from "node:fs";
import { isNotFound } from "#core/predicates/failure.predicate";
import path from "node:path";

const missingOr = function missingOr<T>(error: unknown, fallback: T): T {
    if (error instanceof Error && isNotFound(error)) {
        return fallback;
    }
    throw error;
};

export const readFileSafe = function readFileSafe(file: string): string {
    try {
        return fs.readFileSync(file, "utf8");
    } catch (error) {
        return missingOr(error, "");
    }
};

export const safeReaddir = function safeReaddir(dir: string): fs.Dirent[] {
    try {
        return fs.readdirSync(dir, { withFileTypes: true });
    } catch (error) {
        return missingOr<fs.Dirent[]>(error, []);
    }
};

export const safeStat = function safeStat(target: string): fs.Stats | null {
    try {
        return fs.statSync(target);
    } catch (error) {
        return missingOr(error, null);
    }
};

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

export const readJsonFile = function readJsonFile(file: string): unknown {
    const text = readFileSafe(file);
    return text === "" ? undefined : JSON.parse(text);
};

export const readJsonField = function readJsonField(file: string, key: string): unknown {
    const parsed = readJsonFile(file);
    return isRecord(parsed) ? parsed[key] : undefined;
};

export const walkFiles = function walkFiles(dir: string, excluded: (full: string) => boolean): string[] {
    return safeReaddir(dir).flatMap((entry) => {
        const full = path.join(dir, entry.name);
        const stat = safeStat(full);
        if (stat === null) {
            return [];
        }
        if (excluded(full)) {
            return [];
        }
        return stat.isDirectory() ? walkFiles(full, excluded) : [full];
    });
};
```
