# core/selectors/record.selector.ts

> 44 lines of code and 15 definitions.

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

Listed in [core/selectors](https://banes-lab.com/api/source/quality/core/selectors.md), after [core/selectors/failure.selector.ts](https://banes-lab.com/source/quality/core/selectors/failure.selector.ts.md) and before [core/selectors/syntax.selector.ts](https://banes-lab.com/source/quality/core/selectors/syntax.selector.ts.md).

## Definitions

- `numberField` (lexical_declaration, line 21, exported)
- `recordsAt` (lexical_declaration, line 9, exported)
- `recordAt` (lexical_declaration, line 4, exported)
- `boolField` (lexical_declaration, line 26, exported)
- `stringArrayFieldOr` (lexical_declaration, line 38, exported)
- `hasField` (lexical_declaration, line 28, exported)
- `numericField` (lexical_declaration, line 44, exported)
- `firstNumberField` (lexical_declaration, line 50, exported)
- `stringArrayField` (lexical_declaration, line 35, exported)
- `isRecord` (lexical_declaration, line 1, exported)
- `arrayField` (lexical_declaration, line 30, exported)
- `firstRecord` (lexical_declaration, line 14, exported)
- `stringField` (lexical_declaration, line 16, exported)
- `parsed` (lexical_declaration, line 46, exported)
- `value` (lexical_declaration, line 51, exported)

## Contained in

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

## Used by

- [core/adapters/tool.jscpd.adapter.ts](https://banes-lab.com/source/quality/core/adapters/tool.jscpd.adapter.ts.md)
- [core/adapters/tool.knip.adapter.ts](https://banes-lab.com/source/quality/core/adapters/tool.knip.adapter.ts.md)
- [core/adapters/tool.oxlint.adapter.ts](https://banes-lab.com/source/quality/core/adapters/tool.oxlint.adapter.ts.md)
- [core/adapters/tool.shellcheck.adapter.ts](https://banes-lab.com/source/quality/core/adapters/tool.shellcheck.adapter.ts.md)
- [core/loaders/ecosystem.loader.ts](https://banes-lab.com/source/quality/core/loaders/ecosystem.loader.ts.md)
- [core/loaders/knob.loader.ts](https://banes-lab.com/source/quality/core/loaders/knob.loader.ts.md)
- [core/loaders/quality.loader.ts](https://banes-lab.com/source/quality/core/loaders/quality.loader.ts.md)
- [core/parsers/record.parser.ts](https://banes-lab.com/source/quality/core/parsers/record.parser.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.clippy.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.clippy.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.depcheck.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.depcheck.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.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.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.staticcheck.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.staticcheck.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)
- [core/producers/eslint.producer.ts](https://banes-lab.com/source/quality/core/producers/eslint.producer.ts.md)
- [core/producers/stylelint.producer.ts](https://banes-lab.com/source/quality/core/producers/stylelint.producer.ts.md)
- [runtime/entrypoints/canon.entrypoint.ts](https://banes-lab.com/source/quality/runtime/entrypoints/canon.entrypoint.ts.md)

## Linked from

- [core/adapters](https://banes-lab.com/anatomy/quality/folder-quality-core-adapters.md)
- [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/producers](https://banes-lab.com/anatomy/quality/folder-quality-core-producers.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
export const isRecord = (value: unknown): value is Record<string, unknown> =>
    typeof value === "object" && value !== null && !Array.isArray(value);

export const recordAt = (record: Record<string, unknown>, key: string): Record<string, unknown> => {
    const value = record[key];
    return isRecord(value) ? value : {};
};

export const recordsAt = (record: Record<string, unknown>, key: string): Record<string, unknown>[] => {
    const value = record[key];
    return Array.isArray(value) ? value.filter(isRecord) : [];
};

export const firstRecord = (records: Record<string, unknown>[]): Record<string, unknown> => records[0] ?? {};

export const stringField = (record: Record<string, unknown>, key: string, fallback = ""): string => {
    const value = record[key];
    return typeof value === "string" ? value : fallback;
};

export const numberField = (record: Record<string, unknown>, key: string, fallback: number): number => {
    const value = record[key];
    return typeof value === "number" ? value : fallback;
};

export const boolField = (record: Record<string, unknown>, key: string): boolean => record[key] === true;

export const hasField = (record: Record<string, unknown>, key: string): boolean => (record[key] ?? null) !== null;

export const arrayField = (record: Record<string, unknown>, key: string): unknown[] => {
    const value = record[key];
    return Array.isArray(value) ? value : [];
};

export const stringArrayField = (record: Record<string, unknown>, key: string): string[] =>
    arrayField(record, key).filter((entry): entry is string => typeof entry === "string");

export const stringArrayFieldOr = (
    record: Record<string, unknown>,
    key: string,
    fallback: readonly string[],
): string[] => (Array.isArray(record[key]) ? stringArrayField(record, key) : [...fallback]);

export const numericField = (record: Record<string, unknown>, key: string, fallback: number): number => {
    const value = record[key];
    const parsed = typeof value === "string" || typeof value === "number" ? Number(value) : Number.NaN;
    return parsed || fallback;
};

export const firstNumberField = (record: Record<string, unknown>, key: string, fallback: number): number => {
    const value = record[key];
    if (Array.isArray(value) && value.length > 0 && typeof value[0] === "number") {
        return value[0];
    }
    return fallback;
};
```
