mirror of
https://github.com/morluto/rea.git
synced 2026-10-30 19:35:56 +00:00
72 lines
2.3 KiB
TypeScript
72 lines
2.3 KiB
TypeScript
import type { Evidence } from "../domain/evidence.js";
|
|
import { EvidenceReferenceError } from "../domain/errors.js";
|
|
import { err, ok, type Result } from "../domain/result.js";
|
|
|
|
/** Semantic identity admitted for one authoritative Evidence reference. */
|
|
export interface EvidenceSemanticIdentity {
|
|
readonly operation: string;
|
|
readonly predicate: string;
|
|
}
|
|
|
|
/** Read one Evidence record from an already-authorized authority. */
|
|
export type EvidenceLookup = (evidenceId: string) => Evidence | undefined;
|
|
|
|
/** Resolve IDs without accepting the digest-shaped identifier as proof itself. */
|
|
export const resolveEvidenceReferences = (
|
|
lookup: EvidenceLookup | undefined,
|
|
evidenceIds: readonly string[],
|
|
expected?: readonly EvidenceSemanticIdentity[],
|
|
): Result<Evidence[], EvidenceReferenceError> => {
|
|
const records: Evidence[] = [];
|
|
for (const evidenceId of evidenceIds) {
|
|
const record = lookup?.(evidenceId);
|
|
if (record === undefined)
|
|
return err(
|
|
new EvidenceReferenceError(
|
|
evidenceId,
|
|
"missing",
|
|
expectationDescription(expected),
|
|
null,
|
|
),
|
|
);
|
|
if (expected !== undefined) {
|
|
const operations = expected.filter(
|
|
({ operation }) => operation === record.operation,
|
|
);
|
|
if (operations.length === 0)
|
|
return err(
|
|
new EvidenceReferenceError(
|
|
evidenceId,
|
|
"wrong_operation",
|
|
unique(expected.map(({ operation }) => operation)).join(" | "),
|
|
record.operation,
|
|
),
|
|
);
|
|
if (
|
|
!operations.some(({ predicate }) => predicate === record.predicate_type)
|
|
)
|
|
return err(
|
|
new EvidenceReferenceError(
|
|
evidenceId,
|
|
"wrong_predicate",
|
|
unique(operations.map(({ predicate }) => predicate)).join(" | "),
|
|
record.predicate_type,
|
|
),
|
|
);
|
|
}
|
|
records.push(record);
|
|
}
|
|
return ok(records);
|
|
};
|
|
|
|
const expectationDescription = (
|
|
expected: readonly EvidenceSemanticIdentity[] | undefined,
|
|
): string =>
|
|
expected === undefined
|
|
? "Evidence in the current authority"
|
|
: expected
|
|
.map(({ operation, predicate }) => `${operation}:${predicate}`)
|
|
.join(" | ");
|
|
|
|
const unique = (values: readonly string[]): string[] => [...new Set(values)];
|