# core/loaders/source.loader.ts

> 42 lines of code and 15 definitions.

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

Listed in [core/loaders](https://banes-lab.com/api/source/patterns/core/loaders.md), after [core/loaders/representation.loader.ts](https://banes-lab.com/source/patterns/core/loaders/representation.loader.ts.md).

## Definitions

- `entryFor` (lexical_declaration, line 35)
- `parseFile` (lexical_declaration, line 20, exported)
- `entriesFor` (lexical_declaration, line 42, exported)
- `isMeaningful` (lexical_declaration, line 30)
- `testUsesOf` (lexical_declaration, line 48, exported)
- `PATH_SEP` (lexical_declaration, line 12)
- `queue` (lexical_declaration, line 14)
- `readSourceOrEmpty` (lexical_declaration, line 16, exported)
- `run` (lexical_declaration, line 21, exported)
- `settleParses` (lexical_declaration, line 26, exported)
- `{ nodeType }` (lexical_declaration, line 31)
- `rel` (lexical_declaration, line 36)
- `records` (lexical_declaration, line 37)
- `symbols` (lexical_declaration, line 38)
- `parsed` (lexical_declaration, line 49, exported)

## Contained in

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

## Uses

- [core/analyzers/syntax.analyzer.ts](https://banes-lab.com/source/patterns/core/analyzers/syntax.analyzer.ts.md)
- [core/classifiers/syntax.classifier.ts](https://banes-lab.com/source/patterns/core/classifiers/syntax.classifier.ts.md)
- [core/converters/walk.converter.ts](https://banes-lab.com/source/patterns/core/converters/walk.converter.ts.md)
- [core/loaders/package.loader.ts](https://banes-lab.com/source/patterns/core/loaders/package.loader.ts.md)

## Linked from

- [core/analyzers](https://banes-lab.com/anatomy/patterns/folder-patterns-core-analyzers.md)
- [core/classifiers](https://banes-lab.com/anatomy/patterns/folder-patterns-core-classifiers.md)
- [core/converters](https://banes-lab.com/anatomy/patterns/folder-patterns-core-converters.md)
- [core/loaders](https://banes-lab.com/anatomy/patterns/folder-patterns-core-loaders.md)

## Source

```typescript
import type { FileEntry, Pruned } from "#types/package.types";
import { existsSync, readFileSync } from "node:fs";
import { relative, sep } from "node:path";
import { sourceFiles, testFilesOf } from "#core/loaders/package.loader";
import type { IngestFile } from "#types/code.types";
import { MEANINGFUL_STATES } from "#configuration/constants/walk.constants";
import { identifierNames } from "#core/analyzers/syntax.analyzer";
import { ingestFile } from "#core/parsers/code.parser";
import { namedWalk } from "#core/converters/walk.converter";
import { stateOf } from "#core/classifiers/syntax.classifier";

const PATH_SEP = "/";

const queue: { tail: Promise<unknown> } = { tail: Promise.resolve() };

export const readSourceOrEmpty = function readSourceOrEmpty(file: string): string {
    return existsSync(file) ? readFileSync(file, "utf8") : "";
};

export const parseFile = async function parseFile(file: string): Promise<IngestFile> {
    const run = queue.tail.then(async () => ingestFile(readSourceOrEmpty(file), file));
    queue.tail = Promise.allSettled([run]);
    return run;
};

export const settleParses = async function settleParses(): Promise<void> {
    await queue.tail;
};

const isMeaningful = function isMeaningful(record: Record<string, unknown>): boolean {
    const { nodeType } = record;
    return MEANINGFUL_STATES.has(stateOf(typeof nodeType === "string" ? nodeType : ""));
};

const entryFor = function entryFor(file: string, moduleDir: string, parsed: IngestFile): FileEntry {
    const rel = relative(moduleDir, file).split(sep).join(PATH_SEP);
    const records = parsed.records.map((record) => ({ ...record, file: rel }));
    const symbols = parsed.symbols.map((symbol) => ({ ...symbol, file: rel }));
    return { records, rel, symbols, walk: namedWalk(records.filter(isMeaningful), symbols) };
};

export const entriesFor = async function entriesFor(moduleDir: string, pruned: Pruned): Promise<FileEntry[]> {
    return Promise.all(
        sourceFiles(moduleDir, pruned).map(async (file) => entryFor(file, moduleDir, await parseFile(file))),
    );
};

export const testUsesOf = async function testUsesOf(moduleDir: string, pruned: Pruned): Promise<Set<string>> {
    const parsed = await Promise.all(testFilesOf(moduleDir, pruned).map(async (file) => parseFile(file)));
    return new Set(parsed.flatMap((entry) => identifierNames(entry.records)));
};
```
