# core/analyzers/field.analyzer.ts

> 43 lines of code and 14 definitions.

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

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

## Definitions

- `bind` (lexical_declaration, line 11)
- `factory` (lexical_declaration, line 13)
- `constructor` (method_definition, line 22, exported)
- `BoundRuntime` (interface_declaration, line 6)
- `FieldAnalyzer` (class_declaration, line 18, exported)
- `field` (public_field_definition, line 19, exported)
- `runtimes` (public_field_definition, line 20, exported)
- `update` (method_definition, line 27, exported)
- `produce` (method_definition, line 33, exported)
- `fragments` (lexical_declaration, line 34, exported)
- `emit` (method_definition, line 41, exported)
- `produced` (lexical_declaration, line 42, exported)
- `analysis` (lexical_declaration, line 46, exported)
- `findingNodes` (lexical_declaration, line 47, exported)

## Contained in

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

## Linked from

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

## Source

```typescript
import { analysisNode, findingNode } from "#core/factories/node.factory";
import type { FieldOutput } from "#types/record.types";
import type { RepresentationRuntime } from "#types/representation.types";
import { runtimeFor } from "#core/selectors/representation.selector";

interface BoundRuntime {
    representation: string;
    runtime: RepresentationRuntime;
}

const bind = function bind(field: string, representations: readonly string[]): BoundRuntime[] {
    return representations.flatMap((representation) => {
        const factory = runtimeFor(representation);
        return factory ? [{ representation, runtime: factory(field) }] : [];
    });
};

export class FieldAnalyzer {
    private readonly field: string;
    private readonly runtimes: readonly BoundRuntime[];

    public constructor(field: string, representations: readonly string[]) {
        this.field = field;
        this.runtimes = bind(field, representations);
    }

    public update(chunk: readonly unknown[]): void {
        for (const { runtime } of this.runtimes) {
            runtime.update(chunk);
        }
    }

    public produce(): FieldOutput {
        const fragments = this.runtimes.map((bound) => this.emit(bound));
        return {
            findings: fragments.flatMap((fragment) => fragment.findings),
            nodes: fragments.flatMap((fragment) => fragment.nodes),
        };
    }

    private emit(bound: BoundRuntime): FieldOutput {
        const produced = bound.runtime.findings();
        if (produced.length === 0) {
            return { findings: [], nodes: [] };
        }
        const analysis = analysisNode(this.field, bound.representation);
        const findingNodes = produced.map((finding) => findingNode(analysis.id, finding.name, finding.coordinate));
        return { findings: produced, nodes: [analysis, ...findingNodes] };
    }
}
```
