# core/resolvers/reference.resolver.ts

> 83 lines of code and 16 definitions.

Tree: GovLab Context
Language: typescript
Layer: infrastructure
Canonical: https://banes-lab.com/anatomy/context#file-context-core-resolvers-reference-resolver-ts
Source text: https://banes-lab.com/source/context/core/resolvers/reference.resolver.ts.txt

Listed in [core/resolvers](https://banes-lab.com/api/source/context/core/resolvers.md), after [core/resolvers/reason.resolver.ts](https://banes-lab.com/source/context/core/resolvers/reason.resolver.ts.md) and before [core/resolvers/template.resolver.ts](https://banes-lab.com/source/context/core/resolvers/template.resolver.ts.md).

## Definitions

- `resolveTarget` (lexical_declaration, line 50, exported)
- `collectionRefResolver` (lexical_declaration, line 80, exported)
- `kindRefResolves` (lexical_declaration, line 67, exported)
- `kindsHolding` (lexical_declaration, line 72, exported)
- `resolvePagTarget` (lexical_declaration, line 16)
- `sub` (lexical_declaration, line 21)
- `name` (lexical_declaration, line 29)
- `TargetResolver` (type_alias_declaration, line 39)
- `TARGET_RESOLVERS` (lexical_declaration, line 41)
- `REF_COLLECTIONS` (lexical_declaration, line 48, exported)
- `parseReasonRef` (lexical_declaration, line 58)
- `colon` (lexical_declaration, line 63, exported)
- `parsed` (lexical_declaration, line 68, exported)
- `bareReasonId` (lexical_declaration, line 76, exported)
- `kindMembers` (lexical_declaration, line 83, exported)
- `rest` (lexical_declaration, line 88, exported)

## Contained in

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

## Used by

- [core/factories/context.factory.ts](https://banes-lab.com/source/context/core/factories/context.factory.ts.md)
- [core/validators/algorithm.reference.validator.ts](https://banes-lab.com/source/context/core/validators/algorithm.reference.validator.ts.md)
- [core/validators/architecture.validator.ts](https://banes-lab.com/source/context/core/validators/architecture.validator.ts.md)
- [core/validators/grammar.reference.validator.ts](https://banes-lab.com/source/context/core/validators/grammar.reference.validator.ts.md)
- [core/validators/ontology.validator.ts](https://banes-lab.com/source/context/core/validators/ontology.validator.ts.md)
- [core/validators/reason.reference.validator.ts](https://banes-lab.com/source/context/core/validators/reason.reference.validator.ts.md)

## Linked from

- [core/factories](https://banes-lab.com/anatomy/context/folder-context-core-factories.md)
- [core/resolvers](https://banes-lab.com/anatomy/context/folder-context-core-resolvers.md)
- [core/validators](https://banes-lab.com/anatomy/context/folder-context-core-validators.md)

## Source

```typescript
import type {
    CollectionRefFaces,
    KindMembers,
    PagTargets,
    ReasonRef,
    TargetResolverFaces,
} from "#types/reference.types";
import {
    PAG_SUBCOLLECTIONS,
    REASON_COLLECTION_NAME,
    REASON_PREFIX,
    REF_SEPARATOR,
} from "#configuration/constants/reference.constants";
import { COLLECTIONS } from "#configuration/constants/ontology.constants";

const resolvePagTarget = function resolvePagTarget(pag: PagTargets, localId: string): boolean {
    const colon = localId.indexOf(REF_SEPARATOR);
    if (colon === -1) {
        return pag.documentType(localId.toUpperCase()) !== null;
    }
    const sub = localId.slice(0, colon);
    const rest = localId.slice(colon + 1);
    if (sub === PAG_SUBCOLLECTIONS.keyword) {
        return pag.keyword(rest) !== null;
    }
    if (sub === PAG_SUBCOLLECTIONS.production) {
        return pag.production(rest) !== null;
    }
    const name = rest.toUpperCase();
    if (sub === PAG_SUBCOLLECTIONS.template) {
        return pag.template(name) !== null;
    }
    return (
        (sub === PAG_SUBCOLLECTIONS.documentType || sub === PAG_SUBCOLLECTIONS.doctype) &&
        pag.documentType(name) !== null
    );
};

type TargetResolver = (faces: TargetResolverFaces, localId: string) => boolean;

const TARGET_RESOLVERS: ReadonlyMap<string, TargetResolver> = new Map<string, TargetResolver>([
    [COLLECTIONS.algorithms, (faces, localId) => faces.algo.get(localId) !== null],
    [COLLECTIONS.architecture, (faces, localId) => (faces.arch?.get(localId) ?? null) !== null],
    [COLLECTIONS.lexicon, (faces, localId) => (faces.lex?.resolve(localId) ?? null) !== null],
    [COLLECTIONS.pag, (faces, localId) => (faces.pag ? resolvePagTarget(faces.pag, localId) : false)],
]);

export const REF_COLLECTIONS: ReadonlySet<string> = new Set([...TARGET_RESOLVERS.keys(), REASON_COLLECTION_NAME]);

export const resolveTarget = function resolveTarget(faces: TargetResolverFaces, to: string): boolean {
    const colon = to.indexOf(REF_SEPARATOR);
    if (colon === -1) {
        return false;
    }
    return TARGET_RESOLVERS.get(to.slice(0, colon))?.(faces, to.slice(colon + 1)) ?? false;
};

const parseReasonRef = function parseReasonRef(ref: string): ReasonRef | null {
    if (!ref.startsWith(REASON_PREFIX)) {
        return null;
    }
    const rest = ref.slice(REASON_PREFIX.length);
    const colon = rest.indexOf(REF_SEPARATOR);
    return colon === -1 ? null : { id: rest.slice(colon + 1), kind: rest.slice(0, colon) };
};

export const kindRefResolves = function kindRefResolves(kindMembers: KindMembers, target: string): boolean {
    const parsed = parseReasonRef(target);
    return parsed !== null && (kindMembers.get(parsed.kind)?.has(parsed.id) ?? false);
};

export const kindsHolding = function kindsHolding(kindMembers: KindMembers, id: string): string[] {
    return [...kindMembers].filter(([, ids]) => ids.has(id)).map(([kind]) => kind);
};

export const bareReasonId = function bareReasonId(target: string): string {
    return target.startsWith(REASON_PREFIX) ? target.slice(REASON_PREFIX.length) : target;
};

export const collectionRefResolver = function collectionRefResolver(
    faces: CollectionRefFaces,
): (ref: string) => boolean {
    const kindMembers = faces.reason.kindMembers();
    return (ref) => {
        if (!ref.startsWith(REASON_PREFIX)) {
            return resolveTarget(faces, ref);
        }
        const rest = ref.slice(REASON_PREFIX.length);
        return rest.includes(REF_SEPARATOR)
            ? kindRefResolves(kindMembers, ref)
            : kindsHolding(kindMembers, rest).length === 1;
    };
};
```
