core/stores/algorithm.store.ts
core/stores/algorithm.store.ts is a file in GovLab Context. 67 lines of code and 15 definitions.
import { ALGORITHM_LABEL, COLLECTIONS } from "#configuration/constants/ontology.constants";
import type {
AlgoGrammar,
AlgoGrammarOptions,
ClosureResult,
Cluster,
ConcernJoinRow,
ConcernResolvers,
Contract,
ContractFilter,
ContractIssues,
SymbolEntry,
} from "#types/algorithm.types";
import { clustersOf, concernJoinOf, traverseComposes } from "#core/analyzers/algorithm.analyzer";
import { loadBundledSymbols, loadContracts } from "#core/loaders/algorithm.loader";
import { BaseOntology } from "#core/stores/ontology.store";
import { COMPOSES_RELATION } from "#configuration/constants/algorithm.constants";
import type { Logger } from "#types/ontology.types";
import { ReadAudit } from "#core/observers/record.observer";
import { matchesContract } from "#core/matchers/algorithm.matcher";
import { slugify } from "#core/converters/identifier.converter";
import { unknownClosureId } from "#configuration/strings/algorithm.strings";
export class AlgorithmStore extends BaseOntology<Contract, ContractFilter> implements AlgoGrammar {
private readonly symbolIndex: SymbolEntry[];
private readonly logger?: Logger | undefined;
public constructor(options: AlgoGrammarOptions = {}, audit = new ReadAudit(COLLECTIONS.algorithms)) {
super(loadContracts(audit, options.data), {
audit,
idOf: (contract) => contract.id,
label: ALGORITHM_LABEL,
logger: options.logger,
matches: matchesContract,
});
this.symbolIndex = options.symbols ?? loadBundledSymbols();
this.logger = options.logger;
}
public symbols = (): SymbolEntry[] => [...this.symbolIndex];
public byForce = (force: string): Contract[] => this.query({ force });
public resolveClosure = (ids: string[]): ClosureResult => {
const byId = this.index();
const seed = ids.filter((id) => byId.has(id));
for (const id of ids.filter((candidate) => !byId.has(candidate))) {
this.logger?.warn(unknownClosureId(id));
}
const order = traverseComposes(byId, seed);
return {
closure: order.flatMap((id) => {
const contract = byId.get(id);
return contract ? [contract] : [];
}),
order,
seed,
};
};
public cluster = (): Cluster[] => clustersOf(this.all());
public joinConcerns = (resolvers: ConcernResolvers = {}): ConcernJoinRow[] => concernJoinOf(this.all(), resolvers);
public validateOntology = (): ContractIssues => {
const base = this.validateEdges(
(contract) => [{ relation: COMPOSES_RELATION, targets: contract.composes }],
slugify,
);
return {
danglingComposes: base.danglingEdges.map(({ from, target }) => ({ from, target })),
duplicateIds: base.duplicateIds,
};
};
}