core/resolvers/reference.resolver.ts
core/resolvers/reference.resolver.ts is a file in GovLab Context. 83 lines of code and 16 definitions.
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;
};
};