# rules/eslint/retired-collection-id.eslint.rule.ts

> 63 lines of code and 12 definitions.

Tree: Governance tree
Language: typescript
Canonical: https://banes-lab.com/anatomy/governance#file-governance-rules-eslint-retired-collection-id-eslint-rule-ts
Source text: https://banes-lab.com/source/governance/rules/eslint/retired-collection-id.eslint.rule.ts.txt

Listed in [rules/eslint](https://banes-lab.com/api/source/governance/rules/eslint.md), after [rules/eslint/require-snapshot-coverage.eslint.rule.ts](https://banes-lab.com/source/governance/rules/eslint/require-snapshot-coverage.eslint.rule.ts.md) and before [rules/eslint/strings-composition.eslint.rule.ts](https://banes-lab.com/source/governance/rules/eslint/strings-composition.eslint.rule.ts.md).

## Definitions

- `check` (lexical_declaration, line 25, exported)
- `closingWidth` (lexical_declaration, line 19)
- `templateElement` (method_definition, line 47, exported)
- `create` (method_definition, line 24, exported)
- `literal` (method_definition, line 42, exported)
- `RULES` (lexical_declaration, line 10)
- `QUOTE_WIDTH` (lexical_declaration, line 16)
- `HOLE_OPEN_WIDTH` (lexical_declaration, line 17)
- `source` (lexical_declaration, line 26, exported)
- `inner` (lexical_declaration, line 27, exported)
- `[first]` (lexical_declaration, line 28, exported)
- `rewritten` (lexical_declaration, line 32, exported)

## Uses

- [shared/factories/listener.factory.ts](https://banes-lab.com/source/governance/shared/factories/listener.factory.ts.md)
- [shared/selectors/syntax.selector.ts](https://banes-lab.com/source/governance/shared/selectors/syntax.selector.ts.md)

## Records this file checks

- [Single Source of Truth](https://banes-lab.com/records/architecture/single-source-of-truth.md)

## Source

```typescript
import { COLLECTION_PATH_SEGMENTS, RENAMED_COLLECTIONS } from "../../shared/manifests/vocabulary.manifest.ts";
import type { LocalRule, RuleContext, RuleListener, RuleNode } from "../../types/rule.types.ts";
import { renamedSpans, renamedText } from "../../shared/matchers/word.matcher.ts";
import type { AstNode } from "../../types/syntax.types.ts";
import type { RenameRules } from "../../types/writing.types.ts";
import { defineCheck } from "@govlab/context/check";
import { listener } from "../../shared/factories/listener.factory.ts";
import { locOf } from "../../shared/selectors/syntax.selector.ts";

const RULES: RenameRules = {
    ids: RENAMED_COLLECTIONS,
    pathSegments: COLLECTION_PATH_SEGMENTS,
    wholeId: false,
    words: null,
};
const QUOTE_WIDTH = 1;
const HOLE_OPEN_WIDTH = 2;

const closingWidth = function closingWidth(view: AstNode): number {
    return view["tail"] === true ? QUOTE_WIDTH : HOLE_OPEN_WIDTH;
};

export default {
    create(context: RuleContext): RuleListener {
        const check = function check(view: AstNode, raw: RuleNode, trailing: number): void {
            const source = context.sourceCode.getText(raw);
            const inner = source.slice(QUOTE_WIDTH, source.length - trailing);
            const [first] = renamedSpans(inner, RULES);
            if (first === undefined) {
                return;
            }
            const rewritten =
                source.slice(0, QUOTE_WIDTH) + renamedText(inner, RULES) + source.slice(source.length - trailing);
            context.report({
                data: { from: first.from, to: first.to },
                fix: (fixer) => fixer.replaceText(raw, rewritten),
                loc: locOf(view),
                messageId: "retiredCollectionId",
            });
        };
        return listener({
            literal(view, raw) {
                if (typeof view["value"] === "string") {
                    check(view, raw, QUOTE_WIDTH);
                }
            },
            templateElement(view, raw) {
                check(view, raw, closingWidth(view));
            },
        });
    },
    meta: {
        docs: {
            checks: defineCheck({ detects: [], enforces: ["architecture:single-source-of-truth"] }),
            description:
                "A string names an ontology collection by the id the collection carries now. The rename registry keeps each retired id beside its current one, and a reference, an anchor, a catalog path or a collection name written with a retired id is rewritten to the current id. The registry is data, so a rename is one registry line.",
        },
        fixable: "code",
        messages: {
            retiredCollectionId:
                "'{{from}}' is a retired collection id, and the collection is now '{{to}}'. The fix rewrites the string in place from the rename registry.",
        },
        schema: [],
        type: "problem",
    },
} satisfies LocalRule;
```
