# core/validators/catalog.kind.validator.ts

> 68 lines of code and 19 definitions.

Tree: Bane's Lab Build Scripts
Language: typescript
Layer: processing
Canonical: https://banes-lab.com/anatomy/build-scripts#file-build-scripts-core-validators-catalog-kind-validator-ts
Source text: https://banes-lab.com/source/build-scripts/core/validators/catalog.kind.validator.ts.txt

Listed in [core/validators](https://banes-lab.com/api/source/build-scripts/core/validators.md), after [core/validators/catalog.grammar.validator.ts](https://banes-lab.com/source/build-scripts/core/validators/catalog.grammar.validator.ts.md) and before [core/validators/catalog.location.validator.ts](https://banes-lab.com/source/build-scripts/core/validators/catalog.location.validator.ts.md).

## Definitions

- `findingsOf` (lexical_declaration, line 58, exported)
- `shapeFindings` (lexical_declaration, line 33)
- `schemaFindings` (lexical_declaration, line 39, exported)
- `schemaOf` (lexical_declaration, line 24)
- `JSON_EXTENSION` (lexical_declaration, line 12)
- `SLASH` (lexical_declaration, line 13)
- `ROOT_PATH` (lexical_declaration, line 14)
- `jsonAt` (lexical_declaration, line 16)
- `addressOf` (lexical_declaration, line 20)
- `file` (lexical_declaration, line 25)
- `parsed` (lexical_declaration, line 34)
- `shape` (lexical_declaration, line 35)
- `schemas` (lexical_declaration, line 44, exported)
- `schemaFor` (lexical_declaration, line 45, exported)
- `schema` (lexical_declaration, line 52, exported)
- `found` (lexical_declaration, line 54, exported)
- `kind` (lexical_declaration, line 59, exported)
- `{ found, schema }` (lexical_declaration, line 66, exported)
- `defects` (lexical_declaration, line 67, exported)

## Contained in

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

## Uses

- [core/converters/schema.converter.ts](https://banes-lab.com/source/build-scripts/core/converters/schema.converter.ts.md)

## Used by

- [core/coordinators/validation.coordinator.ts](https://banes-lab.com/source/build-scripts/core/coordinators/validation.coordinator.ts.md)
- [core/validators/graph.validator.ts](https://banes-lab.com/source/build-scripts/core/validators/graph.validator.ts.md)

## Grounds

- [Schema Validation](https://banes-lab.com/records/architecture/schema-validation.md)

## Linked from

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

## Source

```typescript
import { NOT_A_SCHEMA, missingSchema } from "#configuration/strings/catalog.strings";
import { fileOfAddress, schemaLeaf } from "#core/resolvers/catalog.resolver";
import { instanceDefects, schemaShapeDefects } from "#core/validators/schema.validator";
import type { Finding } from "#types/validation.types";
import type { JsonSchema } from "#types/schema.types";
import { SCHEMA_KIND } from "#configuration/constants/catalog.constants";
import { isObjectValue } from "#core/converters/schema.converter";
import { join } from "node:path";
import { kindOrNull } from "#core/converters/catalog.grammar.converter";
import { readFileSync } from "node:fs";

const JSON_EXTENSION = ".json";
const SLASH = "/";
const ROOT_PATH = "$";

const jsonAt = function jsonAt(outDir: string, file: string): unknown {
    return JSON.parse(readFileSync(join(outDir, file), "utf8"));
};

const addressOf = function addressOf(file: string): string {
    return SLASH + file.slice(0, -JSON_EXTENSION.length);
};

const schemaOf = function schemaOf(outDir: string, kind: string, present: ReadonlySet<string>): JsonSchema | null {
    const file = fileOfAddress(schemaLeaf(kind).json);
    if (!present.has(file)) {
        return null;
    }
    const parsed = jsonAt(outDir, file);
    return isObjectValue(parsed) ? parsed : null;
};

const shapeFindings = function shapeFindings(outDir: string, file: string): Finding[] {
    const parsed = jsonAt(outDir, file);
    const shape = isObjectValue(parsed) ? schemaShapeDefects(parsed, ROOT_PATH) : [NOT_A_SCHEMA];
    return shape.map((message) => ({ file, message }));
};

export const schemaFindings = function schemaFindings(
    outDir: string,
    files: readonly string[],
    present: ReadonlySet<string>,
): Finding[] {
    const schemas = new Map<string, JsonSchema | null>();
    const schemaFor = function schemaFor(kind: string): {
        readonly found: Finding[];
        readonly schema: JsonSchema | null;
    } {
        if (schemas.has(kind)) {
            return { found: [], schema: schemas.get(kind) ?? null };
        }
        const schema = schemaOf(outDir, kind, present);
        schemas.set(kind, schema);
        const found =
            schema === null ? [{ file: fileOfAddress(schemaLeaf(kind).json), message: missingSchema(kind) }] : [];
        return { found, schema };
    };
    const findingsOf = function findingsOf(file: string): Finding[] {
        const kind = kindOrNull(addressOf(file));
        if (kind === null) {
            return [];
        }
        if (kind === SCHEMA_KIND) {
            return shapeFindings(outDir, file);
        }
        const { found, schema } = schemaFor(kind);
        const defects =
            schema === null
                ? []
                : instanceDefects(jsonAt(outDir, file), schema, ROOT_PATH).map((message) => ({ file, message }));
        return [...found, ...defects];
    };
    return files.flatMap(findingsOf);
};
```
