# tools/core/resolvers/reference.resolver.ts

> 136 lines of code and 38 definitions.

Tree: Coordination tree
Language: typescript
Layer: infrastructure
Canonical: https://banes-lab.com/anatomy/coordination#file-coordination-tools-core-resolvers-reference-resolver-ts
Source text: https://banes-lab.com/assets/sources/source.bfb8d81b5639ed1be73f0dbd8fc33f87a602adf75f43844d1f1908f1f565a856.generated.txt

## Definitions

- `resolvesCitation` (lexical_declaration, line 61, exported)
- `citationRefusal` (lexical_declaration, line 154, exported)
- `joinedDirectory` (lexical_declaration, line 24)
- `offeredForms` (function_declaration, line 100, exported)
- `registeredGates` (lexical_declaration, line 40)
- `beforeSlash` (lexical_declaration, line 56)
- `isFlagCharacter` (lexical_declaration, line 95)
- `parseCitation` (lexical_declaration, line 135, exported)
- `unknownKind` (lexical_declaration, line 150, exported)
- `Citation` (interface_declaration, line 9, exported)
- `RULES_DIR` (lexical_declaration, line 14)
- `ENTRYPOINT_ROOT` (lexical_declaration, line 16)
- `WRITE_ENTRYPOINT` (lexical_declaration, line 18)
- `PLANNING_DIR` (lexical_declaration, line 19)
- `RULE_SOURCES` (lexical_declaration, line 20)
- `RECORD_SOURCES` (lexical_declaration, line 21)
- `RULE_SUFFIX` (lexical_declaration, line 22)
- `directory` (lexical_declaration, line 41)
- `ids` (lexical_declaration, line 46)
- `slash` (lexical_declaration, line 57)
- `behavior` (lexical_declaration, line 67, exported)
- `held` (lexical_declaration, line 68, exported)
- `FLAG_OPEN` (lexical_declaration, line 91)
- `FLAG_CLOSE` (lexical_declaration, line 93)
- `lower` (lexical_declaration, line 96)
- `entrypoint` (lexical_declaration, line 101, exported)
- `source` (lexical_declaration, line 106, exported)
- `out` (lexical_declaration, line 107, exported)
- `from` (lexical_declaration, line 108, exported)
- `open` (lexical_declaration, line 111, exported)
- `cursor` (lexical_declaration, line 116, exported)
- `flag` (lexical_declaration, line 121, exported)
- `CITATION_KINDS` (lexical_declaration, line 131, exported)
- `SEPARATOR` (lexical_declaration, line 133)
- `at` (lexical_declaration, line 136, exported)
- `kind` (lexical_declaration, line 141, exported)
- `member` (lexical_declaration, line 142, exported)
- `citation` (lexical_declaration, line 158, exported)

## Uses

- [tools/core/formatters/board.formatter.ts](https://banes-lab.com/source/coordination/tools/core/formatters/board.formatter.ts.md)
- [tools/core/resolvers/checklist.resolver.ts](https://banes-lab.com/source/coordination/tools/core/resolvers/checklist.resolver.ts.md)
- [tools/core/strings/reference.strings.ts](https://banes-lab.com/source/coordination/tools/core/strings/reference.strings.ts.md)

## Used by

- [tools/core/validators/archive.validator.ts](https://banes-lab.com/source/coordination/tools/core/validators/archive.validator.ts.md)

## Source

```typescript
import { DIGEST_ROOT, INTEL_ROOT } from "../constants/template.constants.ts";
import { citationKindUnknown, citationUnresolved, citationUntyped } from "../strings/reference.strings.ts";

import { existsSync, readFileSync, readdirSync } from "node:fs";
import { BEHAVIOUR_DOCUMENT } from "../constants/path.constants.ts";
import { join } from "node:path";
import { surfacePath } from "../../../config/surface.config.ts";

export interface Citation {
    readonly kind: string;
    readonly member: string;
}

const RULES_DIR = DIGEST_ROOT;

const ENTRYPOINT_ROOT = surfacePath("entrypoints");

const WRITE_ENTRYPOINT = "board.entrypoint.ts";
const PLANNING_DIR = surfacePath("planning");
const RULE_SOURCES = surfacePath("rules");
const RECORD_SOURCES = INTEL_ROOT;
const RULE_SUFFIX = ".rule.ts";

const joinedDirectory = function joinedDirectory(root: string, relative: string): string {
    const directory = join(root, relative);
    if (!existsSync(directory)) {
        return "";
    }

    let held = "";
    for (const entry of readdirSync(directory, { withFileTypes: true })) {
        if (!entry.isFile()) {
            continue;
        }
        held += readFileSync(join(directory, entry.name), "utf8");
    }
    return held;
};

const registeredGates = function registeredGates(root: string): string[] {
    const directory = join(root, RULE_SOURCES);
    if (!existsSync(directory)) {
        return [];
    }

    const ids: string[] = [];
    for (const entry of readdirSync(directory, { withFileTypes: true })) {
        if (!entry.isFile() || !entry.name.endsWith(RULE_SUFFIX)) {
            continue;
        }
        ids.push(entry.name.slice(0, entry.name.length - RULE_SUFFIX.length));
    }
    return ids;
};

const beforeSlash = function beforeSlash(member: string): string {
    const slash = member.indexOf("/");
    return slash === -1 ? member : member.slice(0, slash);
};

export const resolvesCitation = function resolvesCitation(root: string, archive: string, citation: Citation): boolean {
    if (citation.kind === "changelog") {
        return archive.includes(citation.member);
    }

    if (citation.kind === "rule") {
        const behavior = join(root, BEHAVIOUR_DOCUMENT);
        const held = (existsSync(behavior) ? readFileSync(behavior, "utf8") : "") + joinedDirectory(root, RULES_DIR);
        return held.includes(citation.member);
    }

    if (citation.kind === "gate") {
        return registeredGates(root).includes(beforeSlash(citation.member));
    }

    if (citation.kind === "row") {
        return joinedDirectory(root, PLANNING_DIR).includes(citation.member);
    }

    if (citation.kind === "record") {
        return joinedDirectory(root, RECORD_SOURCES).includes(citation.member);
    }

    if (citation.kind === "form") {
        return offeredForms(root).includes(citation.member);
    }

    return false;
};

const FLAG_OPEN = '"--';

const FLAG_CLOSE = '"';

const isFlagCharacter = function isFlagCharacter(character: string): boolean {
    const lower = character >= "a" && character <= "z";
    return lower || character === "-";
};

export function offeredForms(root: string): string[] {
    const entrypoint = join(root, ENTRYPOINT_ROOT, WRITE_ENTRYPOINT);
    if (!existsSync(entrypoint)) {
        return [];
    }

    const source = readFileSync(entrypoint, "utf8");
    const out: string[] = [];
    let from = 0;

    while (from < source.length) {
        const open = source.indexOf(FLAG_OPEN, from);
        if (open === -1) {
            break;
        }

        let cursor = open + 1;
        while (cursor < source.length && isFlagCharacter(source.charAt(cursor))) {
            cursor += 1;
        }

        const flag = source.slice(open + 1, cursor);
        if (cursor > open + FLAG_OPEN.length && source.charAt(cursor) === FLAG_CLOSE && !out.includes(flag)) {
            out.push(flag);
        }
        from = open + FLAG_OPEN.length;
    }

    return out;
}

export const CITATION_KINDS = ["gate", "row", "rule", "record", "changelog", "form"];

const SEPARATOR = ":";

export const parseCitation = function parseCitation(text: string): Citation | null {
    const at = text.indexOf(SEPARATOR);
    if (at <= 0) {
        return null;
    }

    const kind = text.slice(0, at).trim();
    const member = text.slice(at + 1).trim();
    if (kind.length === 0 || member.length === 0) {
        return null;
    }

    return { kind, member };
};

export const unknownKind = function unknownKind(citation: Citation): boolean {
    return !CITATION_KINDS.includes(citation.kind);
};

export const citationRefusal = function citationRefusal(
    text: string,
    resolves: (citation: Citation) => boolean,
): string | null {
    const citation = parseCitation(text);

    if (citation === null) {
        return citationUntyped(text, CITATION_KINDS);
    }

    if (unknownKind(citation)) {
        return citationKindUnknown(citation.kind, CITATION_KINDS);
    }

    if (resolves(citation)) {
        return null;
    }

    return citationUnresolved(citation.kind, citation.member);
};
```
