# core/persistence/comment.persistence.ts

> 41 lines of code and 10 definitions.

Tree: GovLab Quality
Language: typescript
Layer: infrastructure
Canonical: https://banes-lab.com/anatomy/quality#file-quality-core-persistence-comment-persistence-ts
Source text: https://banes-lab.com/source/quality/core/persistence/comment.persistence.ts.txt

Listed in [core/persistence](https://banes-lab.com/api/source/quality/core/persistence.md), after [core/persistence/catalog.persistence.ts](https://banes-lab.com/source/quality/core/persistence/catalog.persistence.ts.md) and before [core/persistence/edit.persistence.ts](https://banes-lab.com/source/quality/core/persistence/edit.persistence.ts.md).

## Definitions

- `appendExtracted` (lexical_declaration, line 31, exported)
- `isFileComment` (lexical_declaration, line 9)
- `readExisting` (lexical_declaration, line 18)
- `text` (lexical_declaration, line 19)
- `parsed` (lexical_declaration, line 23)
- `keyOf` (lexical_declaration, line 27)
- `existing` (lexical_declaration, line 35, exported)
- `seen` (lexical_declaration, line 36, exported)
- `fresh` (lexical_declaration, line 37, exported)
- `isNew` (lexical_declaration, line 38, exported)

## Contained in

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

## Uses

- [core/adapters/tool.prettier.adapter.ts](https://banes-lab.com/source/quality/core/adapters/tool.prettier.adapter.ts.md)

## Linked from

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

## Source

```typescript
import type { FileComment } from "#types/comment.types";
import { promises as fs } from "node:fs";
import { govlabPrettierConfig } from "#core/adapters/tool.prettier.adapter";
import { isRecord } from "#core/selectors/record.selector";
import path from "node:path";
import { readFileSafe } from "#core/loaders/source.loader";
import { writeCanonicalJson } from "@govlab/canonical-write";

const isFileComment = function isFileComment(value: unknown): value is FileComment {
    return (
        isRecord(value) &&
        typeof value["file"] === "string" &&
        typeof value["line"] === "number" &&
        typeof value["text"] === "string"
    );
};

const readExisting = function readExisting(outPath: string): FileComment[] {
    const text = readFileSafe(outPath);
    if (text === "") {
        return [];
    }
    const parsed: unknown = JSON.parse(text);
    return Array.isArray(parsed) ? parsed.filter(isFileComment) : [];
};

const keyOf = function keyOf(comment: FileComment): string {
    return `${comment.file}::${String(comment.line)}::${comment.text}`;
};

export const appendExtracted = async function appendExtracted(
    outPath: string,
    collected: readonly FileComment[],
): Promise<number> {
    const existing = readExisting(outPath);
    const seen = new Set(existing.map(keyOf));
    const fresh = collected.filter((comment) => {
        const isNew = !seen.has(keyOf(comment));
        seen.add(keyOf(comment));
        return isNew;
    });
    await fs.mkdir(path.dirname(outPath), { recursive: true });
    await writeCanonicalJson(outPath, [...existing, ...fresh], await govlabPrettierConfig(process.cwd()));
    return fresh.length;
};
```
