# core/parsers/record.parser.ts

> 41 lines of code and 8 definitions.

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

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

## Definitions

- `jsonRecordsAt` (lexical_declaration, line 17, exported)
- `jsonRecord` (lexical_declaration, line 27, exported)
- `parseJsonRecords` (lexical_declaration, line 14, exported)
- `parseOr` (lexical_declaration, line 3)
- `jsonArray` (lexical_declaration, line 42, exported)
- `objectEntriesAt` (lexical_declaration, line 45, exported)
- `jsonRecordsFlexible` (lexical_declaration, line 30, exported)
- `list` (lexical_declaration, line 21, exported)

## Contained in

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

## Uses

- [core/selectors/record.selector.ts](https://banes-lab.com/source/quality/core/selectors/record.selector.ts.md)

## Used by

- [core/loaders/canon.loader.ts](https://banes-lab.com/source/quality/core/loaders/canon.loader.ts.md)
- [core/loaders/concept.loader.ts](https://banes-lab.com/source/quality/core/loaders/concept.loader.ts.md)
- [core/loaders/quality.loader.ts](https://banes-lab.com/source/quality/core/loaders/quality.loader.ts.md)
- [core/parsers/report.parser.ts](https://banes-lab.com/source/quality/core/parsers/report.parser.ts.md)
- [core/parsers/tool.actionlint.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.actionlint.parser.ts.md)
- [core/parsers/tool.bandit.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.bandit.parser.ts.md)
- [core/parsers/tool.brakeman.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.brakeman.parser.ts.md)
- [core/parsers/tool.checkov.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.checkov.parser.ts.md)
- [core/parsers/tool.clj-kondo.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.clj-kondo.parser.ts.md)
- [core/parsers/tool.credo.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.credo.parser.ts.md)
- [core/parsers/tool.dependency-cruiser.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.dependency-cruiser.parser.ts.md)
- [core/parsers/tool.golangci-lint.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.golangci-lint.parser.ts.md)
- [core/parsers/tool.gosec.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.gosec.parser.ts.md)
- [core/parsers/tool.hadolint.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.hadolint.parser.ts.md)
- [core/parsers/tool.jscpd.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.jscpd.parser.ts.md)
- [core/parsers/tool.kics.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.kics.parser.ts.md)
- [core/parsers/tool.knip.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.knip.parser.ts.md)
- [core/parsers/tool.madge.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.madge.parser.ts.md)
- [core/parsers/tool.oxlint.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.oxlint.parser.ts.md)
- [core/parsers/tool.phpcs.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.phpcs.parser.ts.md)
- [core/parsers/tool.phpmd.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.phpmd.parser.ts.md)
- [core/parsers/tool.pylint.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.pylint.parser.ts.md)
- [core/parsers/tool.revive.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.revive.parser.ts.md)
- [core/parsers/tool.rubocop.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.rubocop.parser.ts.md)
- [core/parsers/tool.ruff.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.ruff.parser.ts.md)
- [core/parsers/tool.semgrep.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.semgrep.parser.ts.md)
- [core/parsers/tool.shellcheck.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.shellcheck.parser.ts.md)
- [core/parsers/tool.slither.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.slither.parser.ts.md)
- [core/parsers/tool.sqlfluff.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.sqlfluff.parser.ts.md)
- [core/parsers/tool.swiftlint.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.swiftlint.parser.ts.md)
- [core/parsers/tool.tflint.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.tflint.parser.ts.md)
- [core/parsers/tool.trivy.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.trivy.parser.ts.md)
- [runtime/entrypoints/canon.entrypoint.ts](https://banes-lab.com/source/quality/runtime/entrypoints/canon.entrypoint.ts.md)

## Linked from

- [core/loaders](https://banes-lab.com/anatomy/quality/folder-quality-core-loaders.md)
- [core/parsers](https://banes-lab.com/anatomy/quality/folder-quality-core-parsers.md)
- [core/selectors](https://banes-lab.com/anatomy/quality/folder-quality-core-selectors.md)
- [runtime/entrypoints](https://banes-lab.com/anatomy/quality/folder-quality-runtime-entrypoints.md)

## Source

```typescript
import { isRecord, recordAt } from "#core/selectors/record.selector";

const parseOr = function parseOr<T>(text: string, read: (parsed: unknown) => T, fallback: T): T {
    try {
        return read(JSON.parse(text));
    } catch (error) {
        if (error instanceof SyntaxError) {
            return fallback;
        }
        throw error;
    }
};

export const parseJsonRecords = (text: string): Record<string, unknown>[] =>
    parseOr(text, (parsed) => (Array.isArray(parsed) ? parsed.filter(isRecord) : []), []);

export const jsonRecordsAt = (text: string, key: string): Record<string, unknown>[] =>
    parseOr(
        text,
        (parsed) => {
            const list = isRecord(parsed) ? parsed[key] : [];
            return Array.isArray(list) ? list.filter(isRecord) : [];
        },
        [],
    );

export const jsonRecord = (text: string): Record<string, unknown> =>
    parseOr(text, (parsed) => (isRecord(parsed) ? parsed : {}), {});

export const jsonRecordsFlexible = (text: string): Record<string, unknown>[] =>
    parseOr(
        text,
        (parsed) => {
            if (Array.isArray(parsed)) {
                return parsed.filter(isRecord);
            }
            return isRecord(parsed) ? [parsed] : [];
        },
        [],
    );

export const jsonArray = (text: string): unknown[] =>
    parseOr(text, (parsed): unknown[] => (Array.isArray(parsed) ? parsed.map((item: unknown) => item) : []), []);

export const objectEntriesAt = (text: string, key: string): [string, Record<string, unknown>][] =>
    Object.entries(recordAt(jsonRecord(text), key)).filter((entry): entry is [string, Record<string, unknown>] =>
        isRecord(entry[1]),
    );
```
