import { at, isObject, type StateEntity } from "./environmentStateRules.js"; import type { WriteDraft, WriteIo } from "./environmentStateWriteEffects.js"; import type { StateWritePlan } from "./environmentStateWriteRules.js"; /** Whether an update or delete that answers with the entity can answer for an initial entity: one holds, or an update's rules write, every field its recorded response shows. */ const renders = ( plan: StateWritePlan, input: { readonly io: WriteIo; readonly entities: readonly StateEntity[] }, ): boolean => { const { response } = plan; if ( (plan.effect !== "update" && plan.effect !== "delete") || response?.shape !== "entity" ) return true; const shown = input.io.withBody(response.ordinal, (body) => { const object = body === undefined ? undefined : at(body, response.pointer ?? ""); return isObject(object) ? Object.keys(object) : undefined; }); // Serving renders an update's answer from the entity it wrote; an increment only adds to a field held. const written = new Set( plan.effect === "update" ? plan.rules.flatMap((rule) => rule.rule === "increment" ? [] : [rule.field], ) : [], ); return ( shown === undefined || input.entities.some( (entity) => entity.type === plan.target && shown.every( (field) => Object.hasOwn(entity.fields, field) || written.has(field), ), ) ); }; /** A replayed write's plan, served only when it was called, nothing contradicted it, a read confirmed it and its answers can render. */ export const writeVerdict = ( draft: WriteDraft, input: { readonly io: WriteIo; readonly entities: readonly StateEntity[] }, ): StateWritePlan => { const plan = draft.plan; if (plan.reason === null) { if (draft.calls === 0) plan.reason = "no-call"; else if (draft.contradictedBy !== undefined) { plan.reason = "contradicted"; plan.contradicted_by = draft.contradictedBy; } else if (draft.sideEffect) plan.reason = "side-effect"; else if (draft.confirmed.length === 0) plan.reason = "unconfirmed"; else if (!renders(plan, input)) plan.reason = "incomplete-entities"; } plan.served = plan.reason === null; plan.checked_record_ordinals = [...new Set(draft.confirmed)]; return { ...plan }; };