# core/plugins/manifest.catalog.plugin.ts

> 39 lines of code and 5 definitions.

Tree: GovLab Docs
Language: typescript
Layer: infrastructure
Canonical: https://banes-lab.com/anatomy/docs#file-docs-core-plugins-manifest-catalog-plugin-ts
Source text: https://banes-lab.com/source/docs/core/plugins/manifest.catalog.plugin.ts.txt

Listed in [core/plugins](https://banes-lab.com/api/source/docs/core/plugins.md), after [core/plugins/manifest.agent.plugin.ts](https://banes-lab.com/source/docs/core/plugins/manifest.agent.plugin.ts.md) and before [core/plugins/manifest.document.plugin.ts](https://banes-lab.com/source/docs/core/plugins/manifest.document.plugin.ts.md).

## Definitions

- `mapRelationship` (lexical_declaration, line 11)
- `assignCatalogFields` (lexical_declaration, line 20)
- `shortName` (lexical_declaration, line 7)
- `contribute` (method_definition, line 37, exported)
- `plugin` (lexical_declaration, line 36, exported)

## Contained in

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

## Uses

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

## Linked from

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

## Source

```typescript
import type { CatalogEntry, ManifestPlugin, PluginContext, Relationship } from "#types/manifest.types";
import { DEFAULT_MATURITY, PACKAGE_SCOPE } from "#configuration/constants/manifest.constants";
import { arrayField, stringField } from "#core/selectors/record.selector";
import type { Manifest } from "#types/readme.types";
import { isPlainRecord } from "#core/predicates/record.predicate";

const shortName = function shortName(scoped: string): string {
    return scoped.startsWith(PACKAGE_SCOPE) ? scoped.slice(PACKAGE_SCOPE.length) : scoped;
};

const mapRelationship = function mapRelationship(list: unknown): Relationship[] {
    return (Array.isArray(list) ? list : []).flatMap((entry): Relationship[] => {
        if (!isPlainRecord(entry) || typeof entry["package"] !== "string" || typeof entry["reason"] !== "string") {
            return [];
        }
        return [{ package: shortName(entry["package"]), reason: entry["reason"] }];
    });
};

const assignCatalogFields = function assignCatalogFields(
    manifest: Manifest,
    entry: CatalogEntry,
    context: PluginContext,
): void {
    entry["label"] = stringField(manifest, "label") ?? context.module.slug;
    entry["summary"] = stringField(manifest, "summary") ?? "";
    entry["maturity"] = stringField(manifest, "maturity") ?? DEFAULT_MATURITY;
    entry["capabilities"] = arrayField(manifest, "capabilities");
    entry["requires"] = context.requires(context.module.slug);
    entry["overlaps"] = mapRelationship(manifest["overlaps"]);
    entry["incompatibleWith"] = mapRelationship(manifest["incompatibleWith"]);
    entry["supersedes"] = mapRelationship(manifest["supersedes"]);
    entry["ecosystem"] = stringField(manifest, "ecosystem") ?? context.module.ecosystemHint;
};

export const plugin: ManifestPlugin = {
    contribute(manifest, entry, context) {
        if (context) {
            assignCatalogFields(manifest, entry, context);
        }
    },
    name: "catalog",
};
```
