# core/validators/syntax.validator.ts

> 79 lines of code and 14 definitions.

Tree: GovLab Context
Language: typescript
Layer: processing
Canonical: https://banes-lab.com/anatomy/context#file-context-core-validators-syntax-validator-ts
Source text: https://banes-lab.com/source/context/core/validators/syntax.validator.ts.txt

Listed in [core/validators](https://banes-lab.com/api/source/context/core/validators.md), after [core/validators/repair.validator.ts](https://banes-lab.com/source/context/core/validators/repair.validator.ts.md) and before [core/validators/tension.validator.ts](https://banes-lab.com/source/context/core/validators/tension.validator.ts.md).

## Definitions

- `recordsOf` (lexical_declaration, line 35)
- `asciiArrowsIn` (lexical_declaration, line 31, exported)
- `asciiArrowsOf` (lexical_declaration, line 79, exported)
- `reasonArrowsOf` (lexical_declaration, line 43)
- `pagArrowsOf` (lexical_declaration, line 70)
- `arrowFieldsOf` (lexical_declaration, line 16)
- `carriesAsciiArrow` (lexical_declaration, line 12)
- `ASCII_ARROW` (lexical_declaration, line 5)
- `DECLARED_ALTERNATIVE` (lexical_declaration, line 6)
- `PATH_JOINER` (lexical_declaration, line 7)
- `EDGE_ID_PREFIX` (lexical_declaration, line 8)
- `REASONING` (lexical_declaration, line 9)
- `PAG` (lexical_declaration, line 10)
- `withId` (lexical_declaration, line 44)

## Contained in

- [core/validators](https://banes-lab.com/anatomy/context/folder-context-core-validators.md)

## Used by

- [core/validators/ontology.validator.ts](https://banes-lab.com/source/context/core/validators/ontology.validator.ts.md)

## Linked from

- [core/validators](https://banes-lab.com/anatomy/context/folder-context-core-validators.md)

## Source

```typescript
import type { AsciiArrow } from "#types/validation.types";
import { COLLECTIONS } from "#configuration/constants/ontology.constants";
import type { Faces } from "#types/context.types";

const ASCII_ARROW = "->";
const DECLARED_ALTERNATIVE = '"→" | "->"';
const PATH_JOINER = ".";
const EDGE_ID_PREFIX = "edge:";
const REASONING = COLLECTIONS.reasoning;
const PAG = COLLECTIONS.pag;

const carriesAsciiArrow = function carriesAsciiArrow(text: string): boolean {
    return text.split(DECLARED_ALTERNATIVE).some((part) => part.includes(ASCII_ARROW));
};

const arrowFieldsOf = function arrowFieldsOf(value: unknown, path: string): string[] {
    if (typeof value === "string") {
        return carriesAsciiArrow(value) ? [path] : [];
    }
    if (Array.isArray(value)) {
        return value.flatMap((item, index) => arrowFieldsOf(item, `${path}[${String(index)}]`));
    }
    if (typeof value === "object" && value !== null) {
        return Object.entries(value).flatMap(([key, item]) =>
            arrowFieldsOf(item, path === "" ? key : `${path}${PATH_JOINER}${key}`),
        );
    }
    return [];
};

export const asciiArrowsIn = function asciiArrowsIn(collection: string, id: string, record: unknown): AsciiArrow[] {
    return arrowFieldsOf(record, "").map((field) => ({ collection, field, id }));
};

const recordsOf = function recordsOf<R>(
    collection: string,
    records: readonly R[],
    idOf: (record: R) => string,
): AsciiArrow[] {
    return records.flatMap((record) => asciiArrowsIn(collection, idOf(record), record));
};

const reasonArrowsOf = function reasonArrowsOf(reason: Faces["reason"]): AsciiArrow[] {
    const withId = [
        ...reason.layers(),
        ...reason.mathTypes(),
        ...reason.axes(),
        ...reason.nodes(),
        ...reason.dimensions(),
        ...reason.lenses(),
        ...reason.modes(),
        ...reason.representations(),
        ...reason.mathDomains(),
        ...reason.patternTypes(),
        ...reason.models(),
        ...reason.universalAxes(),
        ...reason.testSurfaces(),
        ...reason.techniques(),
        ...reason.invariants(),
        ...reason.failureShapes(),
    ];
    return [
        ...recordsOf(REASONING, withId, (record) => record.id),
        ...asciiArrowsIn(REASONING, "derivation-loop", reason.derivationLoop()),
        ...asciiArrowsIn(REASONING, "substrate", reason.substrate()),
        ...recordsOf(REASONING, reason.edges(), (edge) => `${EDGE_ID_PREFIX}${edge.from}`),
    ];
};

const pagArrowsOf = function pagArrowsOf(pag: Faces["pag"]): AsciiArrow[] {
    return [
        ...recordsOf(PAG, pag.keywords(), (keyword) => keyword.keyword),
        ...recordsOf(PAG, pag.documentTypes(), (documentType) => documentType.type),
        ...recordsOf(PAG, pag.productions(), (production) => production.lhs),
        ...recordsOf(PAG, pag.templates(), (template) => template.type),
    ];
};

export const asciiArrowsOf = function asciiArrowsOf(faces: Faces): AsciiArrow[] {
    return [
        ...recordsOf(COLLECTIONS.architecture, faces.arch.all(), (principle) => principle.id),
        ...recordsOf(COLLECTIONS.lexicon, faces.lex.all(), (term) => term.id),
        ...recordsOf(COLLECTIONS.algorithms, faces.algo.all(), (contract) => contract.id),
        ...reasonArrowsOf(faces.reason),
        ...pagArrowsOf(faces.pag),
    ];
};
```
