# core/analyzers/schema.analyzer.ts

> 31 lines of code and 6 definitions.

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

Listed in [core/analyzers](https://banes-lab.com/api/source/patterns/core/analyzers.md), after [core/analyzers/representation.graph.analyzer.ts](https://banes-lab.com/source/patterns/core/analyzers/representation.graph.analyzer.ts.md) and before [core/analyzers/syntax.analyzer.ts](https://banes-lab.com/source/patterns/core/analyzers/syntax.analyzer.ts.md).

## Definitions

- `accumulatorFor` (lexical_declaration, line 7)
- `detectSchema` (lexical_declaration, line 17, exported)
- `existing` (lexical_declaration, line 8)
- `created` (lexical_declaration, line 12)
- `fields` (lexical_declaration, line 21, exported)
- `count` (lexical_declaration, line 22, exported)

## Contained in

- [core/analyzers](https://banes-lab.com/anatomy/patterns/folder-patterns-core-analyzers.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/analyzers](https://banes-lab.com/anatomy/patterns/folder-patterns-core-analyzers.md)
- [core/predicates](https://banes-lab.com/anatomy/patterns/folder-patterns-core-predicates.md)

## Source

```typescript
import { DataLoadError } from "#core/classifiers/schema.classifier";
import { FieldAccumulator } from "#core/aggregators/field.aggregator";
import type { FieldSchema } from "#types/schema.types";
import { isRecord } from "#core/predicates/record.predicate";
import { notAnObject } from "#configuration/strings/schema.strings";

const accumulatorFor = function accumulatorFor(fields: Map<string, FieldAccumulator>, key: string): FieldAccumulator {
    const existing = fields.get(key);
    if (existing) {
        return existing;
    }
    const created = new FieldAccumulator();
    fields.set(key, created);
    return created;
};

export const detectSchema = function detectSchema(
    records: Iterable<unknown>,
    floatFields: ReadonlySet<string> = new Set(),
): FieldSchema[] {
    const fields = new Map<string, FieldAccumulator>();
    let count = 0;
    for (const record of records) {
        if (!isRecord(record)) {
            throw new DataLoadError(notAnObject(JSON.stringify(record)));
        }
        count += 1;
        for (const [key, value] of Object.entries(record)) {
            accumulatorFor(fields, key).observe(value, floatFields.has(key));
        }
    }
    return [...fields.entries()].map(([name, accumulator]) => accumulator.result(name, count));
};
```
