# runtime/entrypoints/link.entrypoint.ts

> 56 lines of code and 11 definitions.

Tree: Build tree
Language: typescript
Layer: runtime
Canonical: https://banes-lab.com/anatomy/build#file-build-runtime-entrypoints-link-entrypoint-ts
Source text: https://banes-lab.com/assets/sources/source.1672c22b86e31f9265217b351bff3e3d7f9fdb8c51d31c4693c6ee0f62737c02.generated.txt

## Definitions

- `validate` (lexical_declaration, line 45)
- `derive` (lexical_declaration, line 37)
- `builtSections` (lexical_declaration, line 28)
- `argv` (lexical_declaration, line 22)
- `{ missing, sections }` (lexical_declaration, line 29)
- `[first]` (lexical_declaration, line 30)
- `sections` (lexical_declaration, line 38)
- `target` (lexical_declaration, line 39)
- `links` (lexical_declaration, line 41)
- `baseline` (lexical_declaration, line 46)
- `{ lost, moved }` (lexical_declaration, line 50)

## Uses

- [core/loaders/link.loader.ts](https://banes-lab.com/source/build/core/loaders/link.loader.ts.md)
- [core/persistence/report.persistence.ts](https://banes-lab.com/source/build/core/persistence/report.persistence.ts.md)
- [core/reporters/derivation.reporter.ts](https://banes-lab.com/source/build/core/reporters/derivation.reporter.ts.md)

## Source

```typescript
import {
    CLEAN_LINKS,
    LINKS_SUFFIX,
    LINK_LOST,
    LINK_MOVED,
    NO_LINK_SET,
    NO_PAYLOAD,
    SECTIONS_SUFFIX,
    WROTE,
} from "#configuration/strings/derivation.strings";
import { LINK_DERIVE_DESCRIBE, LINK_SUMMARY } from "#configuration/strings/contract.strings";
import { conclude, refuse, say } from "#core/reporters/derivation.reporter";
import { hasFlag, resolveArgv } from "@govlab/argv";
import { linkSetOf, linkTarget, readLinkSet } from "#core/loaders/link.loader";
import { readSections, sitePages } from "#core/loaders/section.loader";
import { DERIVE_FLAG } from "#configuration/constants/leak.constants";
import { LINK_COMMAND } from "#configuration/constants/contract.constants";
import type { PageSection } from "#types/writing.types";
import { linkChanges } from "#core/validators/link.validator";
import { persistJson } from "#core/persistence/report.persistence";

const argv = resolveArgv({
    command: LINK_COMMAND,
    flags: [{ describe: LINK_DERIVE_DESCRIBE, name: DERIVE_FLAG, takesValue: false }],
    summary: LINK_SUMMARY,
});

const builtSections = async function builtSections(): Promise<readonly PageSection[]> {
    const { missing, sections } = readSections(await sitePages());
    const [first] = missing;
    if (first !== undefined) {
        refuse(`${NO_PAYLOAD}${first}`);
    }
    return sections;
};

const derive = async function derive(): Promise<void> {
    const sections = await builtSections();
    const target = linkTarget();
    await persistJson(target, linkSetOf(sections));
    const links = sections.reduce((total, section) => total + section.links.length, 0);
    say(`${WROTE}${target}: ${String(links)}${LINKS_SUFFIX}${String(sections.length)}${SECTIONS_SUFFIX}`);
};

const validate = async function validate(): Promise<void> {
    const baseline = readLinkSet();
    if (baseline === null) {
        refuse(`${NO_LINK_SET}${linkTarget()}`);
    }
    const { lost, moved } = linkChanges(baseline, await builtSections());
    for (const change of moved) {
        say(`${LINK_MOVED}${change.key} ${change.target}`);
    }
    conclude(
        LINK_COMMAND,
        lost.map((change) => ({ file: change.key, message: `${LINK_LOST}${change.target}` })),
        CLEAN_LINKS,
    );
};

await (hasFlag(argv, DERIVE_FLAG) ? derive() : validate());
```
