import type { ObjectResolution, UnionSubject } from "./port"; /** * Why an empty read is `unresolved` and never `present`. * * `readUnion` cannot tell an absent object from one it failed to read, and does * not claim to: its per-document read is wrapped in `try {…} catch { return [] }` * (`readDoc`, in `@ng-eventually/polyfill`'s `src/surface/read-model.ts`), and * documents whose cap this user does not hold are dropped from the batch before * it reads at all. An empty result means absent OR unreadable OR failed, with * nothing to separate them. * * That is not a gap this package has to close, because nothing it does depends on * the answer: an index only ever grows, so every reading leads to the same act — * do not add, and say so. * * The rule lives here, apart from the I/O, for one reason: in the adapter it was * unreachable by any test, and dropping it there left the suite green while a * FAILED read got reported as `skipped: "no-field"` — a failure filed as a * property of the object. That is exactly the misclassification this layer exists * to avoid, so the rule is now a pure function with its own tests. */ export const EMPTY_READ = "the read came back empty — the object is absent, unreadable, or the read failed; " + "the polyfill does not distinguish them, and this layer does not need it to"; /** Turns what a read returned into the two-state answer the curator acts on. */ export function resolutionFromRead(subjects: readonly UnionSubject[]): ObjectResolution { if (subjects.length === 0) return { state: "unresolved", reason: EMPTY_READ }; return { state: "present", subjects }; } /** Turns a read that threw into the same two-state answer. Never `present`. */ export function resolutionFromFailure(error: unknown): ObjectResolution { return { state: "unresolved", reason: String(error) }; }