# core/converters/graph.link.converter.ts

> 50 lines of code and 10 definitions.

Tree: Bane's Lab Build Scripts
Language: typescript
Layer: processing
Canonical: https://banes-lab.com/anatomy/build-scripts#file-build-scripts-core-converters-graph-link-converter-ts
Source text: https://banes-lab.com/source/build-scripts/core/converters/graph.link.converter.ts.txt

Listed in [core/converters](https://banes-lab.com/api/source/build-scripts/core/converters.md), after [core/converters/graph.converter.ts](https://banes-lab.com/source/build-scripts/core/converters/graph.converter.ts.md) and before [core/converters/graph.ontology.converter.ts](https://banes-lab.com/source/build-scripts/core/converters/graph.ontology.converter.ts.md).

## Definitions

- `refsOf` (lexical_declaration, line 13)
- `linkEdges` (lexical_declaration, line 17, exported)
- `evidenceEdges` (lexical_declaration, line 23, exported)
- `FACE_MARK` (lexical_declaration, line 11)
- `{ outgoing }` (lexical_declaration, line 18, exported)
- `to` (lexical_declaration, line 34, exported)
- `routeEdges` (lexical_declaration, line 43, exported)
- `pathOf` (lexical_declaration, line 44, exported)
- `relation` (lexical_declaration, line 45, exported)
- `required` (lexical_declaration, line 46, exported)

## Contained in

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

## Uses

- [configuration/strings/graph.strings.ts](https://banes-lab.com/source/build-scripts/configuration/strings/graph.strings.ts.md)

## Linked from

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

## Source

```typescript
import { BUILDS_ON_RELATION, EVIDENCE_RELATION_ID, LINKS_TO_RELATION } from "@banes-lab/web/constants/graph.constants";
import type { RouteEdges, SiteScope } from "#types/graph.types";
import { CHAPTER_PREFIX } from "#configuration/constants/graph.constants";
import type { EvidenceNode } from "@banes-lab/web/types/evidence.types.js";
import type { GraphEdge } from "@banes-lab/web/types/graph.types.js";
import type { RouteStop } from "#types/learning.types";
import type { WebModules } from "#types/loader.types";
import { sectionEdges } from "#core/converters/section.converter";
import { unresolvedEvidence } from "#configuration/strings/graph.strings";

const FACE_MARK = ":";

const refsOf = function refsOf(links: readonly { readonly ref: string | null }[]): readonly string[] {
    return links.flatMap((link) => (link.ref === null ? [] : [link.ref]));
};

export const linkEdges = function linkEdges(scope: Pick<SiteScope, "linker" | "plans">): readonly GraphEdge[] {
    const { outgoing } = sectionEdges(scope.plans, scope.linker);
    const relation = LINKS_TO_RELATION;
    return [...outgoing.entries()].flatMap(([from, links]) => refsOf(links).map((to) => ({ from, relation, to })));
};

export const evidenceEdges = function evidenceEdges(
    web: Pick<WebModules, "evidence" | "evidenceConstants">,
    targetOf: (node: EvidenceNode) => string | null,
    subjects: readonly string[],
): readonly GraphEdge[] {
    const relation = EVIDENCE_RELATION_ID;
    return subjects.flatMap((from) =>
        web.evidence
            .evidenceFor({ face: from.slice(0, from.indexOf(FACE_MARK)), ref: from }, web.evidenceConstants.EVIDENCE)
            .flatMap((entry) => entry.nodes)
            .map((node) => {
                const to = targetOf(node);
                if (to === null) {
                    throw new Error(unresolvedEvidence(from, node));
                }
                return { from, relation, to };
            }),
    );
};

export const routeEdges = function routeEdges(stops: readonly RouteStop[]): RouteEdges {
    const pathOf = new Map(stops.map((stop) => [stop.id, stop.path]));
    const relation = BUILDS_ON_RELATION;
    const required = stops.flatMap((stop) => stop.requires.map((id) => ({ id, path: pathOf.get(id), stop })));
    return {
        edges: required.flatMap(({ path, stop }) =>
            path === undefined ? [] : [{ from: CHAPTER_PREFIX + stop.path, relation, to: CHAPTER_PREFIX + path }],
        ),
        unresolved: required
            .filter(({ path }) => path === undefined)
            .map(({ id, stop }) => ({ from: CHAPTER_PREFIX + stop.path, label: id, relation })),
    };
};
```
