# core/parsers/schema.parser.ts

> 35 lines of code and 7 definitions.

Tree: GovLab Patterns
Language: typescript
Layer: processing
Canonical: https://banes-lab.com/anatomy/patterns#file-patterns-core-parsers-schema-parser-ts
Source text: https://banes-lab.com/source/patterns/core/parsers/schema.parser.ts.txt

Listed in [core/parsers](https://banes-lab.com/api/source/patterns/core/parsers.md), after [core/parsers/field.parser.ts](https://banes-lab.com/source/patterns/core/parsers/field.parser.ts.md) and before [core/parsers/syntax.parser.ts](https://banes-lab.com/source/patterns/core/parsers/syntax.parser.ts.md).

## Definitions

- `isKind` (lexical_declaration, line 9)
- `isPrimitive` (lexical_declaration, line 13)
- `fieldFromDict` (lexical_declaration, line 17)
- `KIND_NAMES` (lexical_declaration, line 6)
- `PRIMITIVE_NAMES` (lexical_declaration, line 7)
- `{ name, kind, primitive, fixedLength, elementNumeric, nullable }` (lexical_declaration, line 21)
- `schemaFromDict` (lexical_declaration, line 35, exported)

## Contained in

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

## Uses

- [configuration/strings/schema.strings.ts](https://banes-lab.com/source/patterns/configuration/strings/schema.strings.ts.md)
- [core/predicates/record.predicate.ts](https://banes-lab.com/source/patterns/core/predicates/record.predicate.ts.md)

## Linked from

- [configuration/strings](https://banes-lab.com/anatomy/patterns/folder-patterns-configuration-strings.md)
- [core/parsers](https://banes-lab.com/anatomy/patterns/folder-patterns-core-parsers.md)
- [core/predicates](https://banes-lab.com/anatomy/patterns/folder-patterns-core-predicates.md)

## Source

```typescript
import type { FieldSchema, Kind, Primitive } from "#types/schema.types";
import { SCHEMA_NOT_ARRAY, invalidSchemaField } from "#configuration/strings/schema.strings";
import { DataLoadError } from "#core/classifiers/schema.classifier";
import { isRecord } from "#core/predicates/record.predicate";

const KIND_NAMES: ReadonlySet<string> = new Set(["list-of-objects", "list", "object", "scalar"]);
const PRIMITIVE_NAMES: ReadonlySet<string> = new Set(["boolean", "float", "integer", "string"]);

const isKind = function isKind(value: unknown): value is Kind {
    return typeof value === "string" && KIND_NAMES.has(value);
};

const isPrimitive = function isPrimitive(value: unknown): value is Primitive {
    return typeof value === "string" && PRIMITIVE_NAMES.has(value);
};

const fieldFromDict = function fieldFromDict(raw: unknown): FieldSchema {
    if (!isRecord(raw)) {
        throw new DataLoadError(invalidSchemaField(JSON.stringify(raw)));
    }
    const { name, kind, primitive, fixedLength, elementNumeric, nullable } = raw;
    if (typeof name !== "string" || !isKind(kind)) {
        throw new DataLoadError(invalidSchemaField(JSON.stringify(raw)));
    }
    return {
        elementNumeric: elementNumeric === true,
        fixedLength: typeof fixedLength === "number" ? fixedLength : null,
        kind,
        name,
        nullable: nullable === true,
        primitive: isPrimitive(primitive) ? primitive : null,
    };
};

export const schemaFromDict = function schemaFromDict(data: unknown): FieldSchema[] {
    if (!Array.isArray(data)) {
        throw new DataLoadError(SCHEMA_NOT_ARRAY);
    }
    return data.map(fieldFromDict);
};
```
