import { CorrectiveCommandRegistry } from "./corrective-command-registry"; import { CorrectiveCaseRunnerError, MainMutationCommand } from "./corrective-case-runner"; import { CORRECTIVE_FAMILIES, CorrectiveFamily } from "./corrective-family-runner"; import { InMemoryMainStore, runAtomicMutation } from "./corrective-main-transaction"; export interface GenericFamilyMain { family: CorrectiveFamily; value: string; } const VALUE = /^[A-Za-z0-9._:-]{1,128}$/u; function payload(command: MainMutationCommand): { family: CorrectiveFamily; value: string } { const input = command.payload; if (typeof input.family !== "string" || !CORRECTIVE_FAMILIES.includes(input.family as CorrectiveFamily) || typeof input.value !== "string" || !VALUE.test(input.value) || Object.keys(input).some((key) => !["family", "value"].includes(key))) { throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", "family payload must contain only a bounded family and value"); } return { family: input.family as CorrectiveFamily, value: input.value }; } export function createGenericFamilyMain(family: CorrectiveFamily, value = "before", revision = 1, dirty = false): InMemoryMainStore { return new InMemoryMainStore({ family, value }, revision, dirty, (state) => ({ ...state })); } export function createGenericFamilyRegistry(main: InMemoryMainStore): CorrectiveCommandRegistry { return new CorrectiveCommandRegistry().register({ commandType: "familySetState", targetKinds: ["DATABLOCK", "SCENE"], authorizations: ["USER_EDIT", "SYSTEM"], execute: async (command) => { const change = payload(command); return runAtomicMutation(main, command, (draft) => { if (draft.family !== change.family) throw new CorrectiveCaseRunnerError("INVALID_CONTEXT", "family does not match Main"); const previous = draft.value; draft.value = change.value; return { delta: { family: change.family, previous, value: change.value }, persistence: { dirty: true } }; }); }, }); }