# core/loaders/diagram.loader.ts

> 51 lines of code and 15 definitions.

Tree: Bane's Lab Build Scripts
Language: typescript
Layer: infrastructure
Canonical: https://banes-lab.com/anatomy/build-scripts#file-build-scripts-core-loaders-diagram-loader-ts
Source text: https://banes-lab.com/source/build-scripts/core/loaders/diagram.loader.ts.txt

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

## Definitions

- `collectSources` (lexical_declaration, line 18)
- `discoverSources` (lexical_declaration, line 48, exported)
- `STRINGS_CONCERN` (lexical_declaration, line 10)
- `STRINGS_SUFFIX` (lexical_declaration, line 11)
- `DIAGRAM_KIND` (lexical_declaration, line 12)
- `KIND_SLOT` (lexical_declaration, line 13)
- `TEXT_SLOT` (lexical_declaration, line 14)
- `MEMBER` (lexical_declaration, line 15)
- `MEMBER_BELOW_ROOT` (lexical_declaration, line 16)
- `text` (lexical_declaration, line 23)
- `stringsFiles` (lexical_declaration, line 32)
- `byCodePoint` (lexical_declaration, line 44)
- `sources` (lexical_declaration, line 49, exported)
- `seen` (lexical_declaration, line 50, exported)
- `loaded` (lexical_declaration, line 51, exported)

## Contained in

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

## Linked from

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

## Source

```typescript
import { absolutePath, relativePath } from "@ssot/paths";
import { Buffer } from "node:buffer";
import type { ModuleImporter } from "#types/loader.types";
import { concernFolders } from "@ssot/govlab/shared/resolvers/container.resolver.ts";
import { isRecord } from "#core/selectors/base.selector";
import { join } from "node:path";
import { projectDirs } from "@ssot/govlab/shared/resolvers/anchor.resolver.ts";
import { readdirSync } from "node:fs";

const STRINGS_CONCERN = "strings";
const STRINGS_SUFFIX = ".strings.ts";
const DIAGRAM_KIND = "mermaid";
const KIND_SLOT = "kind";
const TEXT_SLOT = "text";
const MEMBER = relativePath("app.member");
const MEMBER_BELOW_ROOT = `${MEMBER.slice(MEMBER.indexOf("/") + 1)}/`;

const collectSources = function collectSources(value: unknown, into: Set<string>, seen: Set<object>): void {
    if (!isRecord(value) || seen.has(value)) {
        return;
    }
    seen.add(value);
    const text = value[TEXT_SLOT];
    if (value[KIND_SLOT] === DIAGRAM_KIND && typeof text === "string") {
        into.add(text);
    }
    for (const nested of Object.values(value)) {
        collectSources(nested, into, seen);
    }
};

const stringsFiles = function stringsFiles(): string[] {
    return concernFolders(STRINGS_CONCERN, projectDirs())
        .filter((folder) => folder.startsWith(MEMBER_BELOW_ROOT))
        .map((folder) => absolutePath("app.root", folder))
        .flatMap((folder) =>
            readdirSync(folder)
                .filter((name) => name.endsWith(STRINGS_SUFFIX))
                .sort((a, b) => a.localeCompare(b))
                .map((name) => join(folder, name)),
        );
};

const byCodePoint = function byCodePoint(a: string, b: string): number {
    return Buffer.compare(Buffer.from(a), Buffer.from(b));
};

export const discoverSources = async function discoverSources(runner: ModuleImporter): Promise<readonly string[]> {
    const sources = new Set<string>();
    const seen = new Set<object>();
    const loaded = await Promise.all(stringsFiles().map(async (file) => runner.import<unknown>(file)));
    for (const module of loaded) {
        collectSources(module, sources, seen);
    }
    return [...sources].sort(byCodePoint);
};
```
