# core/loaders/document.loader.ts

> 32 lines of code and 5 definitions.

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

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

## Definitions

- `walkDocs` (lexical_declaration, line 12)
- `abs` (lexical_declaration, line 14)
- `collectDocArch` (lexical_declaration, line 30, exported)
- `base` (lexical_declaration, line 31, exported)
- `docs` (lexical_declaration, line 32, exported)

## Contained in

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

## Uses

- [core/loaders/folder.loader.ts](https://banes-lab.com/source/stats/core/loaders/folder.loader.ts.md)
- [core/selectors/document.selector.ts](https://banes-lab.com/source/stats/core/selectors/document.selector.ts.md)
- [runtime/entrypoints/metric.entrypoint.ts](https://banes-lab.com/source/stats/runtime/entrypoints/metric.entrypoint.ts.md)

## Linked from

- [core/loaders](https://banes-lab.com/anatomy/stats/folder-stats-core-loaders.md)
- [core/selectors](https://banes-lab.com/anatomy/stats/folder-stats-core-selectors.md)
- [runtime/entrypoints](https://banes-lab.com/anatomy/stats/folder-stats-runtime-entrypoints.md)

## Source

```typescript
import type { DocArchStats, DocInfo } from "#types/document.types";
import { NO_STATUS, ROOT_FORM, STATUS_KEY } from "#configuration/constants/document.constants";
import { MARKDOWN_EXTENSION } from "#configuration/constants/agent.constants";
import type { PathExclusion } from "@govlab/quality/config";
import { frontmatterValue } from "#core/selectors/document.selector";
import path from "node:path";
import { readFileSync } from "node:fs";
import { readdirSafe } from "#core/loaders/folder.loader";
import { relativePath } from "@ssot/paths";
import { tally } from "#core/selectors/metric.selector";

const walkDocs = function walkDocs(absDir: string, base: string, ignore: PathExclusion): DocInfo[] {
    return readdirSafe(absDir).flatMap((entry): DocInfo[] => {
        const abs = path.join(absDir, entry.name);
        if (entry.isDirectory() && !ignore(abs)) {
            return walkDocs(abs, base, ignore);
        }
        if (!entry.isFile() || !entry.name.toLowerCase().endsWith(MARKDOWN_EXTENSION)) {
            return [];
        }
        return [
            {
                form: path.relative(base, abs).split(path.sep).at(0) ?? ROOT_FORM,
                status: frontmatterValue(readFileSync(abs, "utf8"), STATUS_KEY) ?? NO_STATUS,
            },
        ];
    });
};

export const collectDocArch = function collectDocArch(root: string, ignore: PathExclusion): DocArchStats {
    const base = path.join(root, relativePath("docArch"));
    const docs = walkDocs(base, base, ignore);
    return { byForm: tally(docs, (doc) => doc.form), byStatus: tally(docs, (doc) => doc.status), total: docs.length };
};
```
