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

> 90 lines of code and 34 definitions.

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

Listed in [tools/core/resolvers](https://banes-lab.com/api/source/coordination/tools/core/resolvers.md), after [tools/core/resolvers/dependency.resolver.ts](https://banes-lab.com/source/coordination/tools/core/resolvers/dependency.resolver.ts.md) and before [tools/core/resolvers/gate.resolver.ts](https://banes-lab.com/source/coordination/tools/core/resolvers/gate.resolver.ts.md).

## Definitions

- `functionBody` (lexical_declaration, line 18)
- `mutationRoots` (lexical_declaration, line 45)
- `functionEntry` (lexical_declaration, line 24)
- `presenceBackedMutationGuards` (lexical_declaration, line 90, exported)
- `DECLARE_CONST` (lexical_declaration, line 4)
- `FUNCTION_WORD` (lexical_declaration, line 6)
- `FUNCTION_LEADS` (lexical_declaration, line 8)
- `BLOCK_CLOSE` (lexical_declaration, line 10)
- `constEntry` (lexical_declaration, line 12)
- `equals` (lexical_declaration, line 14)
- `rest` (lexical_declaration, line 19)
- `end` (lexical_declaration, line 20)
- `name` (lexical_declaration, line 32)
- `declarationBodies` (lexical_declaration, line 36)
- `entries` (lexical_declaration, line 37)
- `entry` (lexical_declaration, line 39)
- `roots` (lexical_declaration, line 49)
- `trimmed` (lexical_declaration, line 50)
- `value` (lexical_declaration, line 51)
- `searchGuard` (lexical_declaration, line 57)
- `seen` (lexical_declaration, line 64)
- `chain` (lexical_declaration, line 65)
- `frontier` (lexical_declaration, line 66)
- `level` (lexical_declaration, line 68)
- `identifiers` (lexical_declaration, line 69)
- `hit` (lexical_declaration, line 70)
- `scanned` (lexical_declaration, line 71)
- `unseen` (lexical_declaration, line 72)
- `expanding` (lexical_declaration, line 73)
- `reader` (lexical_declaration, line 80)
- `lines` (lexical_declaration, line 96, exported)
- `bodies` (lexical_declaration, line 97, exported)
- `presence` (lexical_declaration, line 98, exported)
- `found` (lexical_declaration, line 103, exported)

## Source

```typescript
import { identifiersIn, memberKey, memberValue, wordFrom } from "../analyzers/source.analyzer.ts";
import type { PresenceBackedGuard } from "../types/entrypoint.types.ts";

const DECLARE_CONST = "const ";

const FUNCTION_WORD = "function ";

const FUNCTION_LEADS = ["function ", "async function ", "export function ", "export async function "];

const BLOCK_CLOSE = "}";

const constEntry = function constEntry(trimmed: string): [string, string] | null {
    const name = wordFrom(trimmed, DECLARE_CONST.length);
    const equals = trimmed.indexOf("=");
    return name.length > 0 && equals !== -1 ? [name, trimmed.slice(equals + 1)] : null;
};

const functionBody = function functionBody(lines: readonly string[], index: number): string {
    const rest = lines.slice(index + 1);
    const end = rest.findIndex((line) => line.startsWith(BLOCK_CLOSE));
    return (end === -1 ? rest : rest.slice(0, end)).map((line) => `${line}\n`).join("");
};

const functionEntry = function functionEntry(
    lines: readonly string[],
    index: number,
    trimmed: string,
): [string, string] | null {
    if (!FUNCTION_LEADS.some((lead) => trimmed.startsWith(lead))) {
        return null;
    }
    const name = wordFrom(trimmed, trimmed.indexOf(FUNCTION_WORD) + FUNCTION_WORD.length);
    return name.length === 0 ? null : [name, functionBody(lines, index)];
};

const declarationBodies = function declarationBodies(lines: readonly string[]): Map<string, string> {
    const entries = lines.flatMap((line, index) => {
        const trimmed = line.trim();
        const entry = trimmed.startsWith(DECLARE_CONST) ? constEntry(trimmed) : functionEntry(lines, index, trimmed);
        return entry === null ? [] : [entry];
    });
    return new Map(entries.toReversed());
};

const mutationRoots = function mutationRoots(
    lines: readonly string[],
    fields: ReadonlySet<string>,
): Map<string, number> {
    const roots = lines.flatMap((line, index): [string, number][] => {
        const trimmed = line.trim();
        const value = fields.has(memberKey(trimmed)) ? memberValue(trimmed) : "";
        return value.length > 0 ? [[value, index + 1]] : [];
    });
    return new Map(roots.toReversed());
};

const searchGuard = function searchGuard(
    guard: string,
    line: number,
    bodies: ReadonlyMap<string, string>,
    presence: ReadonlySet<string>,
    depth: number,
): PresenceBackedGuard | null {
    const seen = new Set<string>([guard]);
    const chain: string[] = [guard];
    let frontier: readonly string[] = [guard];

    for (let level = 0; level < depth && frontier.length > 0; level += 1) {
        const identifiers = frontier.flatMap((name) => identifiersIn(bodies.get(name) ?? ""));
        const hit = identifiers.findIndex((identifier) => presence.has(identifier));
        const scanned = hit === -1 ? identifiers : identifiers.slice(0, hit);
        const unseen = [...new Set(scanned)].filter((identifier) => !seen.has(identifier));
        const expanding = unseen.filter((identifier) => bodies.has(identifier));

        for (const identifier of unseen) {
            seen.add(identifier);
        }
        chain.push(...expanding);

        const reader = identifiers[hit];
        if (reader !== undefined) {
            return { chain: [...chain, reader], guard, line, reader };
        }
        frontier = expanding;
    }

    return null;
};

export const presenceBackedMutationGuards = function presenceBackedMutationGuards(
    source: string,
    mutationFields: readonly string[],
    presenceReaders: readonly string[],
    depth: number,
): PresenceBackedGuard[] {
    const lines = source.split("\n");
    const bodies = declarationBodies(lines);
    const presence = new Set(presenceReaders);

    return [...mutationRoots(lines, new Set(mutationFields))]
        .toSorted((left, right) => left[1] - right[1])
        .flatMap(([guard, line]) => {
            const found = searchGuard(guard, line, bodies, presence, depth);
            return found === null ? [] : [found];
        });
};
```
